Updated on 2026-08-14
This commit is contained in:
parent
2471b9c1a8
commit
941863f79b
18 changed files with 334 additions and 43 deletions
|
|
@ -525,8 +525,11 @@ class MainActivity : AppCompatActivity(), ActivityResultCallbackHolder {
|
||||||
|
|
||||||
// Workaround to navigate to TangemPayDetails screen. Will be deleted in next PRs
|
// Workaround to navigate to TangemPayDetails screen. Will be deleted in next PRs
|
||||||
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
if (tangemPayFeatureToggles.isTangemPayEnabled) {
|
||||||
|
lifecycleScope.launch {
|
||||||
|
val selectedUserWalledId = userWalletsListRepository.selectedUserWalletSync()?.walletId
|
||||||
store.dispatchNavigationAction {
|
store.dispatchNavigationAction {
|
||||||
replaceAll(AppRoute.TangemPayDetails)
|
replaceAll(AppRoute.TangemPayDetails(requireNotNull(selectedUserWalledId)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
|
} else if (userWalletsListManager.isLockable && userWalletsListManager.hasUserWallets) {
|
||||||
store.dispatchNavigationAction {
|
store.dispatchNavigationAction {
|
||||||
|
|
|
||||||
|
|
@ -591,7 +591,7 @@ internal class ChildFactory @Inject constructor(
|
||||||
is AppRoute.TangemPayDetails -> {
|
is AppRoute.TangemPayDetails -> {
|
||||||
createComponentChild(
|
createComponentChild(
|
||||||
context = context,
|
context = context,
|
||||||
params = TangemPayDetailsComponent.Params(),
|
params = TangemPayDetailsComponent.Params(userWalletId = route.userWalletId),
|
||||||
componentFactory = tangemPayDetailsComponentFactory,
|
componentFactory = tangemPayDetailsComponentFactory,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -369,5 +369,5 @@ sealed class AppRoute(val path: String) : Route {
|
||||||
) : AppRoute(path = "/archived_account/${userWalletId.stringValue}")
|
) : AppRoute(path = "/archived_account/${userWalletId.stringValue}")
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data object TangemPayDetails : AppRoute(path = "/tangem_pay_details")
|
data class TangemPayDetails(val userWalletId: UserWalletId) : AppRoute(path = "/tangem_pay_details")
|
||||||
}
|
}
|
||||||
|
|
@ -23,7 +23,7 @@ import java.util.UUID
|
||||||
* @param modifier modifier
|
* @param modifier modifier
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TxHistoryGroupTitle(config: TxHistoryItemState.GroupTitle, modifier: Modifier = Modifier) {
|
fun TxHistoryGroupTitle(config: TxHistoryItemState.GroupTitle, modifier: Modifier = Modifier) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.background(TangemTheme.colors.background.primary)
|
.background(TangemTheme.colors.background.primary)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,9 @@ dependencies {
|
||||||
implementation(projects.core.decompose)
|
implementation(projects.core.decompose)
|
||||||
implementation(projects.core.ui)
|
implementation(projects.core.ui)
|
||||||
|
|
||||||
|
/** Domain */
|
||||||
|
implementation(projects.domain.models)
|
||||||
|
|
||||||
/** Compose */
|
/** Compose */
|
||||||
implementation(deps.compose.runtime)
|
implementation(deps.compose.runtime)
|
||||||
}
|
}
|
||||||
|
|
@ -2,9 +2,9 @@ package com.tangem.features.tangempay.components
|
||||||
|
|
||||||
import com.tangem.core.decompose.factory.ComponentFactory
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
import com.tangem.core.ui.decompose.ComposableContentComponent
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
|
||||||
interface TangemPayDetailsComponent : ComposableContentComponent {
|
interface TangemPayDetailsComponent : ComposableContentComponent {
|
||||||
@Suppress("EmptyDefaultConstructor") // Will add params in Next PRs
|
data class Params(val userWalletId: UserWalletId)
|
||||||
class Params()
|
|
||||||
interface Factory : ComponentFactory<Params, TangemPayDetailsComponent>
|
interface Factory : ComponentFactory<Params, TangemPayDetailsComponent>
|
||||||
}
|
}
|
||||||
|
|
@ -19,6 +19,12 @@ dependencies {
|
||||||
|
|
||||||
/** Features api */
|
/** Features api */
|
||||||
implementation(projects.features.tangempay.details.api)
|
implementation(projects.features.tangempay.details.api)
|
||||||
|
implementation(projects.features.txhistory.api)
|
||||||
|
|
||||||
|
/** Domain */
|
||||||
|
implementation(projects.domain.balanceHiding)
|
||||||
|
implementation(projects.domain.balanceHiding.models)
|
||||||
|
implementation(projects.domain.models)
|
||||||
|
|
||||||
/** Compose */
|
/** Compose */
|
||||||
implementation(deps.compose.foundation)
|
implementation(deps.compose.foundation)
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,10 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
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.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
|
import com.tangem.core.ui.components.NavigationBar3ButtonsScrim
|
||||||
|
import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent
|
||||||
import com.tangem.features.tangempay.model.TangemPayDetailsModel
|
import com.tangem.features.tangempay.model.TangemPayDetailsModel
|
||||||
import com.tangem.features.tangempay.ui.TangemPayDetailsScreen
|
import com.tangem.features.tangempay.ui.TangemPayDetailsScreen
|
||||||
import dagger.assisted.Assisted
|
import dagger.assisted.Assisted
|
||||||
|
|
@ -19,12 +21,16 @@ internal class DefaultTangemPayDetailsComponent @AssistedInject constructor(
|
||||||
) : AppComponentContext by appComponentContext, TangemPayDetailsComponent {
|
) : AppComponentContext by appComponentContext, TangemPayDetailsComponent {
|
||||||
|
|
||||||
private val model: TangemPayDetailsModel = getOrCreateModel(params = params)
|
private val model: TangemPayDetailsModel = getOrCreateModel(params = params)
|
||||||
|
private val txHistoryComponent = DefaultTangemPayTxHistoryComponent(
|
||||||
|
appComponentContext = child("txHistoryComponent"),
|
||||||
|
params = DefaultTangemPayTxHistoryComponent.Params(userWalletId = params.userWalletId),
|
||||||
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content(modifier: Modifier) {
|
override fun Content(modifier: Modifier) {
|
||||||
val state by model.uiState.collectAsStateWithLifecycle()
|
val state by model.uiState.collectAsStateWithLifecycle()
|
||||||
NavigationBar3ButtonsScrim()
|
NavigationBar3ButtonsScrim()
|
||||||
TangemPayDetailsScreen(state = state, modifier = modifier)
|
TangemPayDetailsScreen(state = state, txHistoryComponent = txHistoryComponent, modifier = modifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
@AssistedFactory
|
@AssistedFactory
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.tangem.features.tangempay.components.txHistory
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
|
import com.tangem.domain.models.wallet.UserWalletId
|
||||||
|
import com.tangem.features.tangempay.model.TangemPayTxHistoryModel
|
||||||
|
import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
import com.tangem.features.txhistory.ui.txHistoryItems
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
internal class DefaultTangemPayTxHistoryComponent(
|
||||||
|
appComponentContext: AppComponentContext,
|
||||||
|
params: Params,
|
||||||
|
) : AppComponentContext by appComponentContext, TangemPayTxHistoryComponent {
|
||||||
|
|
||||||
|
private val model: TangemPayTxHistoryModel = getOrCreateModel(params = params)
|
||||||
|
override val state: StateFlow<TxHistoryUM> = model.uiState
|
||||||
|
|
||||||
|
override fun LazyListScope.txHistoryContent(listState: LazyListState, state: TxHistoryUM) {
|
||||||
|
txHistoryItems(listState, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class Params(val userWalletId: UserWalletId)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,174 @@
|
||||||
|
package com.tangem.features.tangempay.components.txHistory
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||||
|
import com.tangem.core.ui.extensions.stringReference
|
||||||
|
import com.tangem.features.tangempay.details.impl.R
|
||||||
|
import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
import com.tangem.features.txhistory.ui.txHistoryItems
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
internal class PreviewTangemPayTxHistoryComponent(txHistoryUM: TxHistoryUM) : TangemPayTxHistoryComponent {
|
||||||
|
override val state: StateFlow<TxHistoryUM> = MutableStateFlow(txHistoryUM)
|
||||||
|
|
||||||
|
override fun LazyListScope.txHistoryContent(listState: LazyListState, state: TxHistoryUM) {
|
||||||
|
txHistoryItems(listState, state)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val loadingUM = TxHistoryUM.Loading(isBalanceHidden = true, onExploreClick = {})
|
||||||
|
val emptyUM = TxHistoryUM.Empty(isBalanceHidden = true, onExploreClick = {})
|
||||||
|
val contentUM = TxHistoryUM.Content(
|
||||||
|
isBalanceHidden = false,
|
||||||
|
loadMore = { false },
|
||||||
|
items = persistentListOf(
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Title(onExploreClick = {}),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.GroupTitle(title = "Today", itemKey = "Today"),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-4.99 USD",
|
||||||
|
time = "16:41",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Starbucks"),
|
||||||
|
subtitle = stringReference("Food&Drinks"),
|
||||||
|
timestamp = 3464,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-126.20 USD",
|
||||||
|
time = "12:04",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Wallmart"),
|
||||||
|
subtitle = stringReference("Supermarket"),
|
||||||
|
timestamp = 3465,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.GroupTitle(title = "Yesterday", itemKey = "Yesterday"),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-4.99 USD",
|
||||||
|
time = "21:41",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Starbucks"),
|
||||||
|
subtitle = stringReference("Food&Drinks"),
|
||||||
|
timestamp = 3464,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-126.20 USD",
|
||||||
|
time = "10:04",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Wallmart"),
|
||||||
|
subtitle = stringReference("Supermarket"),
|
||||||
|
timestamp = 3465,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-4.99 USD",
|
||||||
|
time = "19:41",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Starbucks"),
|
||||||
|
subtitle = stringReference("Food&Drinks"),
|
||||||
|
timestamp = 3464,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-126.20 USD",
|
||||||
|
time = "18:04",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Wallmart"),
|
||||||
|
subtitle = stringReference("Supermarket"),
|
||||||
|
timestamp = 3465,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-4.99 USD",
|
||||||
|
time = "17:41",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Starbucks"),
|
||||||
|
subtitle = stringReference("Food&Drinks"),
|
||||||
|
timestamp = 3464,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-126.20 USD",
|
||||||
|
time = "16:04",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Wallmart"),
|
||||||
|
subtitle = stringReference("Supermarket"),
|
||||||
|
timestamp = 3465,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-4.99 USD",
|
||||||
|
time = "15:41",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Starbucks"),
|
||||||
|
subtitle = stringReference("Food&Drinks"),
|
||||||
|
timestamp = 3464,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TxHistoryUM.TxHistoryItemUM.Transaction(
|
||||||
|
state = TransactionState.Content(
|
||||||
|
txHash = "signiferumque",
|
||||||
|
amount = "-126.20 USD",
|
||||||
|
time = "14:04",
|
||||||
|
status = TransactionState.Content.Status.Confirmed,
|
||||||
|
direction = TransactionState.Content.Direction.OUTGOING,
|
||||||
|
onClick = {},
|
||||||
|
iconRes = R.drawable.ic_arrow_up_24,
|
||||||
|
title = stringReference("Wallmart"),
|
||||||
|
subtitle = stringReference("Supermarket"),
|
||||||
|
timestamp = 3465,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.tangem.features.tangempay.components.txHistory
|
||||||
|
|
||||||
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
|
import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
|
internal interface TangemPayTxHistoryComponent {
|
||||||
|
val state: StateFlow<TxHistoryUM>
|
||||||
|
fun LazyListScope.txHistoryContent(listState: LazyListState, state: TxHistoryUM)
|
||||||
|
}
|
||||||
|
|
@ -3,6 +3,7 @@ package com.tangem.features.tangempay.di
|
||||||
import com.tangem.core.decompose.di.ModelComponent
|
import com.tangem.core.decompose.di.ModelComponent
|
||||||
import com.tangem.core.decompose.model.Model
|
import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.features.tangempay.model.TangemPayDetailsModel
|
import com.tangem.features.tangempay.model.TangemPayDetailsModel
|
||||||
|
import com.tangem.features.tangempay.model.TangemPayTxHistoryModel
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
|
@ -16,5 +17,10 @@ internal interface TangemPayModelModule {
|
||||||
@Binds
|
@Binds
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ClassKey(TangemPayDetailsModel::class)
|
@ClassKey(TangemPayDetailsModel::class)
|
||||||
fun bindWcConnectionsModel(model: TangemPayDetailsModel): Model
|
fun bindTangemPayDetailsModel(model: TangemPayDetailsModel): Model
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(TangemPayTxHistoryModel::class)
|
||||||
|
fun bindTangemPayTxHistoryModel(model: TangemPayTxHistoryModel): Model
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.tangem.features.tangempay.model
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import com.tangem.core.decompose.di.ModelScoped
|
||||||
|
import com.tangem.core.decompose.model.Model
|
||||||
|
import com.tangem.core.decompose.model.ParamsContainer
|
||||||
|
import com.tangem.domain.balancehiding.GetBalanceHidingSettingsUseCase
|
||||||
|
import com.tangem.features.tangempay.components.txHistory.DefaultTangemPayTxHistoryComponent
|
||||||
|
import com.tangem.features.tangempay.components.txHistory.PreviewTangemPayTxHistoryComponent
|
||||||
|
import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import timber.log.Timber
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
@ModelScoped
|
||||||
|
internal class TangemPayTxHistoryModel @Inject constructor(
|
||||||
|
private val getBalanceHidingSettingsUseCase: GetBalanceHidingSettingsUseCase,
|
||||||
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
paramsContainer: ParamsContainer,
|
||||||
|
) : Model() {
|
||||||
|
|
||||||
|
private val params: DefaultTangemPayTxHistoryComponent.Params = paramsContainer.require()
|
||||||
|
|
||||||
|
val uiState: StateFlow<TxHistoryUM>
|
||||||
|
field = MutableStateFlow(getInitialState())
|
||||||
|
|
||||||
|
init {
|
||||||
|
handleBalanceHiding()
|
||||||
|
subscribeToUiItemChanges()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("MagicNumber")
|
||||||
|
private fun subscribeToUiItemChanges() {
|
||||||
|
modelScope.launch {
|
||||||
|
Timber.d("subscribeToUiItemChanges: ${params.userWalletId}")
|
||||||
|
delay(2000)
|
||||||
|
uiState.update { PreviewTangemPayTxHistoryComponent.contentUM }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleBalanceHiding() {
|
||||||
|
getBalanceHidingSettingsUseCase()
|
||||||
|
.onEach { uiState.update { state -> state.copySealed(isBalanceHidden = it.isBalanceHidden) } }
|
||||||
|
.launchIn(modelScope)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun onExploreClick() {
|
||||||
|
Timber.d("onExploreClick: open explorer")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getInitialState(): TxHistoryUM {
|
||||||
|
return TxHistoryUM.Loading(isBalanceHidden = true, onExploreClick = ::onExploreClick)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -19,11 +19,13 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Devices
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.util.fastForEach
|
import androidx.compose.ui.util.fastForEach
|
||||||
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
import com.tangem.core.ui.components.RectangleShimmer
|
import com.tangem.core.ui.components.RectangleShimmer
|
||||||
import com.tangem.core.ui.components.buttons.HorizontalActionChips
|
import com.tangem.core.ui.components.buttons.HorizontalActionChips
|
||||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||||
|
|
@ -37,6 +39,8 @@ import com.tangem.core.ui.extensions.resourceReference
|
||||||
import com.tangem.core.ui.res.TangemTheme
|
import com.tangem.core.ui.res.TangemTheme
|
||||||
import com.tangem.core.ui.res.TangemThemePreview
|
import com.tangem.core.ui.res.TangemThemePreview
|
||||||
import com.tangem.core.ui.test.TokenDetailsTopBarTestTags
|
import com.tangem.core.ui.test.TokenDetailsTopBarTestTags
|
||||||
|
import com.tangem.features.tangempay.components.txHistory.PreviewTangemPayTxHistoryComponent
|
||||||
|
import com.tangem.features.tangempay.components.txHistory.TangemPayTxHistoryComponent
|
||||||
import com.tangem.features.tangempay.details.impl.R
|
import com.tangem.features.tangempay.details.impl.R
|
||||||
import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM
|
import com.tangem.features.tangempay.entity.TangemPayCardDetailsUM
|
||||||
import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState
|
import com.tangem.features.tangempay.entity.TangemPayDetailsBalanceBlockState
|
||||||
|
|
@ -46,7 +50,11 @@ import com.tangem.utils.StringsSigns.DASH_SIGN
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun TangemPayDetailsScreen(state: TangemPayDetailsUM, modifier: Modifier = Modifier) {
|
internal fun TangemPayDetailsScreen(
|
||||||
|
state: TangemPayDetailsUM,
|
||||||
|
txHistoryComponent: TangemPayTxHistoryComponent,
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
Scaffold(
|
Scaffold(
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
topBar = { TangemPayDetailsTopAppBar(config = state.topBarConfig) },
|
topBar = { TangemPayDetailsTopAppBar(config = state.topBarConfig) },
|
||||||
|
|
@ -55,6 +63,7 @@ internal fun TangemPayDetailsScreen(state: TangemPayDetailsUM, modifier: Modifie
|
||||||
) { scaffoldPaddings ->
|
) { scaffoldPaddings ->
|
||||||
val listState = rememberLazyListState()
|
val listState = rememberLazyListState()
|
||||||
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
|
val bottomBarHeight = with(LocalDensity.current) { WindowInsets.systemBars.getBottom(this).toDp() }
|
||||||
|
val txHistoryState by txHistoryComponent.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
TangemPullToRefreshContainer(
|
TangemPullToRefreshContainer(
|
||||||
config = state.pullToRefreshConfig,
|
config = state.pullToRefreshConfig,
|
||||||
|
|
@ -91,6 +100,8 @@ internal fun TangemPayDetailsScreen(state: TangemPayDetailsUM, modifier: Modifie
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
with(txHistoryComponent) { txHistoryContent(listState = listState, state = txHistoryState) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -317,14 +328,19 @@ private fun TangemPayDetailsTopAppBar(config: TangemPayDetailsTopBarConfig, modi
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Preview(showBackground = true, widthDp = 360)
|
@Preview(device = Devices.PIXEL_7_PRO, group = "day")
|
||||||
@Preview(showBackground = true, widthDp = 360, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, device = Devices.PIXEL_7_PRO, group = "night")
|
||||||
@Composable
|
@Composable
|
||||||
private fun TangemPayDetailsScreenPreview(
|
private fun TangemPayDetailsScreenPreview(
|
||||||
@PreviewParameter(TangemPayDetailsUMProvider::class) state: TangemPayDetailsUM,
|
@PreviewParameter(TangemPayDetailsUMProvider::class) state: TangemPayDetailsUM,
|
||||||
) {
|
) {
|
||||||
TangemThemePreview {
|
TangemThemePreview {
|
||||||
TangemPayDetailsScreen(state = state)
|
TangemPayDetailsScreen(
|
||||||
|
state = state,
|
||||||
|
txHistoryComponent = PreviewTangemPayTxHistoryComponent(
|
||||||
|
txHistoryUM = PreviewTangemPayTxHistoryComponent.contentUM,
|
||||||
|
),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.tangem.features.txhistory.entity
|
package com.tangem.features.txhistory.entity
|
||||||
|
|
||||||
import com.tangem.core.ui.components.transactions.state.TransactionState
|
import com.tangem.core.ui.components.transactions.state.TransactionState
|
||||||
|
import com.tangem.core.ui.components.transactions.state.TxHistoryState
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
|
@ -81,7 +82,9 @@ sealed interface TxHistoryUM {
|
||||||
data class GroupTitle(
|
data class GroupTitle(
|
||||||
val title: String,
|
val title: String,
|
||||||
val itemKey: String,
|
val itemKey: String,
|
||||||
) : TxHistoryItemUM
|
) : TxHistoryItemUM {
|
||||||
|
val legacyGroupTitle = TxHistoryState.TxHistoryItemState.GroupTitle(title = title, itemKey = itemKey)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transaction item
|
* Transaction item
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,16 @@
|
||||||
package com.tangem.features.txhistory.ui
|
package com.tangem.features.txhistory.ui
|
||||||
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.heightIn
|
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.foundation.lazy.itemsIndexed
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
import androidx.compose.material3.Text
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Alignment
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import com.tangem.core.ui.components.list.InfiniteListHandler
|
import com.tangem.core.ui.components.list.InfiniteListHandler
|
||||||
import com.tangem.core.ui.components.transactions.PendingTxsBlock
|
import com.tangem.core.ui.components.transactions.PendingTxsBlock
|
||||||
import com.tangem.core.ui.components.transactions.Transaction
|
import com.tangem.core.ui.components.transactions.Transaction
|
||||||
|
import com.tangem.core.ui.components.transactions.TxHistoryGroupTitle
|
||||||
import com.tangem.core.ui.components.transactions.TxHistoryTitle
|
import com.tangem.core.ui.components.transactions.TxHistoryTitle
|
||||||
import com.tangem.core.ui.components.transactions.empty.EmptyTransactionBlock
|
import com.tangem.core.ui.components.transactions.empty.EmptyTransactionBlock
|
||||||
import com.tangem.core.ui.components.transactions.empty.EmptyTransactionsBlockState
|
import com.tangem.core.ui.components.transactions.empty.EmptyTransactionsBlockState
|
||||||
|
|
@ -25,7 +21,7 @@ import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
|
||||||
private const val LOAD_ITEMS_BUFFER = 20
|
private const val LOAD_ITEMS_BUFFER = 20
|
||||||
|
|
||||||
internal fun LazyListScope.txHistoryItems(listState: LazyListState, state: TxHistoryUM) {
|
fun LazyListScope.txHistoryItems(listState: LazyListState, state: TxHistoryUM) {
|
||||||
when (state) {
|
when (state) {
|
||||||
is TxHistoryUM.Content -> contentItems(listState, state)
|
is TxHistoryUM.Content -> contentItems(listState, state)
|
||||||
is TxHistoryUM.Empty -> nonContentItem(state = EmptyTransactionsBlockState.Empty(state.onExploreClick))
|
is TxHistoryUM.Empty -> nonContentItem(state = EmptyTransactionsBlockState.Empty(state.onExploreClick))
|
||||||
|
|
@ -127,7 +123,7 @@ internal fun TxHistoryListItem(
|
||||||
) {
|
) {
|
||||||
when (state) {
|
when (state) {
|
||||||
is TxHistoryUM.TxHistoryItemUM.GroupTitle -> {
|
is TxHistoryUM.TxHistoryItemUM.GroupTitle -> {
|
||||||
TxHistoryGroupTitle(config = state, modifier = modifier)
|
TxHistoryGroupTitle(config = state.legacyGroupTitle, modifier = modifier)
|
||||||
}
|
}
|
||||||
is TxHistoryUM.TxHistoryItemUM.Title -> {
|
is TxHistoryUM.TxHistoryItemUM.Title -> {
|
||||||
TxHistoryTitle(onExploreClick = state.onExploreClick, modifier = modifier)
|
TxHistoryTitle(onExploreClick = state.onExploreClick, modifier = modifier)
|
||||||
|
|
@ -141,24 +137,3 @@ internal fun TxHistoryListItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun TxHistoryGroupTitle(config: TxHistoryUM.TxHistoryItemUM.GroupTitle, modifier: Modifier = Modifier) {
|
|
||||||
Box(
|
|
||||||
modifier = modifier
|
|
||||||
.background(TangemTheme.colors.background.primary)
|
|
||||||
.padding(
|
|
||||||
vertical = TangemTheme.dimens.spacing8,
|
|
||||||
horizontal = TangemTheme.dimens.spacing12,
|
|
||||||
)
|
|
||||||
.fillMaxWidth()
|
|
||||||
.heightIn(min = TangemTheme.dimens.size24),
|
|
||||||
contentAlignment = Alignment.CenterStart,
|
|
||||||
) {
|
|
||||||
Text(
|
|
||||||
text = config.title,
|
|
||||||
color = TangemTheme.colors.text.tertiary,
|
|
||||||
style = TangemTheme.typography.body2,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,7 +2,6 @@ package com.tangem.features.txhistory.component
|
||||||
|
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
import androidx.compose.foundation.lazy.LazyListState
|
import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.compose.runtime.*
|
|
||||||
import com.tangem.core.decompose.context.AppComponentContext
|
import com.tangem.core.decompose.context.AppComponentContext
|
||||||
import com.tangem.core.decompose.model.getOrCreateModel
|
import com.tangem.core.decompose.model.getOrCreateModel
|
||||||
import com.tangem.features.txhistory.entity.TxHistoryUM
|
import com.tangem.features.txhistory.entity.TxHistoryUM
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ internal fun BaseExtension.configureCompose(project: Project) {
|
||||||
contains(Regex(pattern = ":app\$")) || // TODO: [REDACTED_JIRA]
|
contains(Regex(pattern = ":app\$")) || // TODO: [REDACTED_JIRA]
|
||||||
contains(Regex(pattern = ":features:markets:api\$")) || // provides Composable function
|
contains(Regex(pattern = ":features:markets:api\$")) || // provides Composable function
|
||||||
contains(Regex(pattern = ":features:manage-tokens:api\$")) || // provides Composable function
|
contains(Regex(pattern = ":features:manage-tokens:api\$")) || // provides Composable function
|
||||||
|
contains(Regex(pattern = ":features:txhistory:api\$")) || // provides Composable function
|
||||||
contains(Regex(pattern = ":impl\$"))
|
contains(Regex(pattern = ":impl\$"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue