Updated on 2026-08-14
This commit is contained in:
commit
86d48eb6f3
22 changed files with 991 additions and 99 deletions
|
|
@ -8,6 +8,7 @@ import android.os.Bundle
|
|||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.Result
|
||||
import com.otaliastudios.cameraview.CameraView.PERMISSION_REQUEST_CODE
|
||||
import me.dm7.barcodescanner.zxing.ZXingScannerView
|
||||
|
|
@ -16,11 +17,15 @@ import me.dm7.barcodescanner.zxing.ZXingScannerView
|
|||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class ScanQrCodeActivity : AppCompatActivity(), ZXingScannerView.ResultHandler {
|
||||
|
||||
private lateinit var mScannerView: ZXingScannerView
|
||||
|
||||
override fun onCreate(state: Bundle?) {
|
||||
super.onCreate(state)
|
||||
mScannerView = ZXingScannerView(this)
|
||||
|
||||
mScannerView = ZXingScannerView(this).apply {
|
||||
setFormats(listOf(BarcodeFormat.QR_CODE))
|
||||
}
|
||||
setContentView(mScannerView)
|
||||
|
||||
if (!permissionIsGranted()) requestPermission()
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import androidx.activity.OnBackPressedCallback
|
|||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.WindowCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.zxing.BarcodeFormat
|
||||
import com.google.zxing.Result
|
||||
import com.otaliastudios.cameraview.CameraView
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
|
|
@ -38,10 +39,19 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
|
|||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||
if (!permissionIsGranted()) requestPermission()
|
||||
|
||||
scannerView = ZXingScannerView(activity)
|
||||
scannerView = ZXingScannerView(activity).apply {
|
||||
setFormats(listOf(BarcodeFormat.QR_CODE))
|
||||
}
|
||||
|
||||
return scannerView
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
scannerView?.setResultHandler(this)
|
||||
scannerView?.startCamera()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
scannerView?.stopCamera()
|
||||
|
|
@ -52,12 +62,6 @@ class QrScanFragment : Fragment(0), ZXingScannerView.ResultHandler {
|
|||
setFitSystemWindows(fit = false)
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
scannerView?.setResultHandler(this)
|
||||
scannerView?.startCamera()
|
||||
}
|
||||
|
||||
override fun handleResult(result: Result) {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
setFitSystemWindows(fit = false)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency
|
||||
package com.tangem.core.ui.components.marketprice
|
||||
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -17,22 +17,17 @@ import androidx.compose.ui.tooling.preview.Preview
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.RectangleShimmer
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.state.PriceChangeConfig
|
||||
import com.tangem.feature.wallet.presentation.wallet.state.WalletMarketplaceBlockState
|
||||
|
||||
/**
|
||||
* Wallet marketplace block
|
||||
*
|
||||
* @param state state
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
* @see <a href =
|
||||
* "https://www.figma.com/file/14ISV23YB1yVW1uNVwqrKv/Android?type=design&node-id=1217-922&mode=design&t=t1PxyisyGJSwzQwg-4"
|
||||
* >Figma component</a>
|
||||
*/
|
||||
@Composable
|
||||
internal fun WalletMarketplaceBlock(state: WalletMarketplaceBlockState, modifier: Modifier = Modifier) {
|
||||
fun MarketPriceBlock(state: MarketPriceBlockState, modifier: Modifier = Modifier) {
|
||||
var rootWidth by remember { mutableStateOf(value = 0) }
|
||||
Column(
|
||||
modifier = modifier
|
||||
|
|
@ -54,12 +49,12 @@ internal fun WalletMarketplaceBlock(state: WalletMarketplaceBlockState, modifier
|
|||
)
|
||||
|
||||
when (state) {
|
||||
is WalletMarketplaceBlockState.Loading -> {
|
||||
is MarketPriceBlockState.Loading -> {
|
||||
RectangleShimmer(
|
||||
modifier = Modifier.size(width = TangemTheme.dimens.size158, height = TangemTheme.dimens.size20),
|
||||
)
|
||||
}
|
||||
is WalletMarketplaceBlockState.Content -> {
|
||||
is MarketPriceBlockState.Content -> {
|
||||
Price(
|
||||
config = state,
|
||||
priceWidthDp = with(LocalDensity.current) { rootWidth.div(other = 2).toDp() },
|
||||
|
|
@ -70,7 +65,7 @@ internal fun WalletMarketplaceBlock(state: WalletMarketplaceBlockState, modifier
|
|||
}
|
||||
|
||||
@Composable
|
||||
private fun Price(config: WalletMarketplaceBlockState.Content, priceWidthDp: Dp) {
|
||||
private fun Price(config: MarketPriceBlockState.Content, priceWidthDp: Dp) {
|
||||
Row(
|
||||
modifier = Modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
|
@ -124,35 +119,44 @@ private fun PriceChangeInPercent(config: PriceChangeConfig) {
|
|||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_MarketplaceBlock_Light(
|
||||
@PreviewParameter(WalletMarketplaceStateProvider::class)
|
||||
state: WalletMarketplaceBlockState,
|
||||
private fun Preview_MarketPriceBlock_Light(
|
||||
@PreviewParameter(WalletMarketPriceBlockStateProvider::class)
|
||||
state: MarketPriceBlockState,
|
||||
) {
|
||||
TangemTheme(isDark = false) {
|
||||
WalletMarketplaceBlock(state = state)
|
||||
MarketPriceBlock(state = state)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
private fun Preview_MarketplaceBlock_Dark(
|
||||
@PreviewParameter(WalletMarketplaceStateProvider::class)
|
||||
state: WalletMarketplaceBlockState,
|
||||
private fun Preview_MarketPriceBlock_Dark(
|
||||
@PreviewParameter(WalletMarketPriceBlockStateProvider::class)
|
||||
state: MarketPriceBlockState,
|
||||
) {
|
||||
TangemTheme(isDark = true) {
|
||||
WalletMarketplaceBlock(state = state)
|
||||
MarketPriceBlock(state = state)
|
||||
}
|
||||
}
|
||||
|
||||
private class WalletMarketplaceStateProvider : CollectionPreviewParameterProvider<WalletMarketplaceBlockState>(
|
||||
private class WalletMarketPriceBlockStateProvider : CollectionPreviewParameterProvider<MarketPriceBlockState>(
|
||||
collection = listOf(
|
||||
WalletPreviewData.marketplaceBlockContent,
|
||||
WalletPreviewData.marketplaceBlockContent.copy(
|
||||
MarketPriceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "98900",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "5.16%",
|
||||
type = PriceChangeConfig.Type.DOWN,
|
||||
),
|
||||
),
|
||||
WalletMarketplaceBlockState.Loading(currencyName = "BTC"),
|
||||
MarketPriceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "98900",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "10.89%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
MarketPriceBlockState.Loading(currencyName = "BTC"),
|
||||
),
|
||||
)
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.core.ui.components.marketprice
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface MarketPriceBlockState {
|
||||
|
||||
val currencyName: String
|
||||
|
||||
data class Loading(override val currencyName: String) : MarketPriceBlockState
|
||||
|
||||
data class Content(
|
||||
override val currencyName: String,
|
||||
val price: String,
|
||||
val priceChangeConfig: PriceChangeConfig,
|
||||
) : MarketPriceBlockState
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package com.tangem.core.ui.components.marketprice
|
||||
|
||||
data class PriceChangeConfig(val valueInPercent: String, val type: Type) {
|
||||
|
||||
/** Price changing type */
|
||||
enum class Type {
|
||||
UP, DOWN
|
||||
}
|
||||
}
|
||||
|
|
@ -7,4 +7,7 @@ dependencies {
|
|||
implementation(projects.domain.core)
|
||||
implementation(projects.domain.wallets.models)
|
||||
implementation(projects.core.utils)
|
||||
|
||||
testImplementation(deps.test.junit)
|
||||
testImplementation(deps.test.coroutine)
|
||||
}
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
package com.tangem.domain.tokens
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.left
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.tokens.error.TokensError
|
||||
import com.tangem.domain.tokens.mock.MockNetworks
|
||||
import com.tangem.domain.tokens.mock.MockQuotes
|
||||
import com.tangem.domain.tokens.mock.MockTokenLists
|
||||
import com.tangem.domain.tokens.mock.MockTokens
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.model.Token
|
||||
import com.tangem.domain.tokens.repository.MockNetworksRepository
|
||||
import com.tangem.domain.tokens.repository.MockQuotesRepository
|
||||
import com.tangem.domain.tokens.repository.MockTokensRepository
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import com.tangem.utils.coroutines.TestingCoroutineDispatcherProvider
|
||||
import junit.framework.TestCase.assertEquals
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
internal class GetTokenListUseCaseTest {
|
||||
|
||||
private val dispatchers = TestingCoroutineDispatcherProvider()
|
||||
private val userWalletId = UserWalletId(value = null)
|
||||
|
||||
@Test
|
||||
fun `when list ungrouped and unsorted then correct token list should be returned`() = runTest {
|
||||
// Given
|
||||
val expectedResult = MockTokenLists.ungroupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(
|
||||
isGrouped = flowOf(false.right()),
|
||||
isSortedByBalance = flowOf(false.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyTokens.left()
|
||||
|
||||
val useCase = getUseCase(tokens = flowOf(expectedResult))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyQuotes.left()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf(expectedResult))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks getting failed and list is groped then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyNetworkStatues.left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = expectedResult,
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyNetworkStatues.left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf(expectedResult))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when grouping type getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyTokens.left()
|
||||
|
||||
val useCase = getUseCase(isGrouped = flowOf(expectedResult))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when sorting type getting failed then error should be received`() = runTest {
|
||||
// Given
|
||||
val expectedResult = TokensError.EmptyTokens.left()
|
||||
|
||||
val useCase = getUseCase(isSortedByBalance = flowOf(expectedResult))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens getting failed on second emit then error should be received`() = runTest {
|
||||
// Given
|
||||
val error = TokensError.EmptyTokens.left()
|
||||
val expectedResult = listOf(
|
||||
MockTokenLists.ungroupedTokenList.right(),
|
||||
error,
|
||||
)
|
||||
|
||||
val useCase = getUseCase(
|
||||
tokens = flowOf(
|
||||
MockTokens.tokens.right(),
|
||||
error,
|
||||
),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId)
|
||||
.take(count = 2)
|
||||
.toList()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list grouped then correct token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.groupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(isGrouped = flowOf(true.right()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is grouped and networks getting failed then error should be received`() = runTest {
|
||||
val expectedResult = TokensError.EmptyNetworks.left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = expectedResult,
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is sorted and ungrouped then correct token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.sortedUngroupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(
|
||||
statuses = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
isGrouped = flowOf(false.right()),
|
||||
isSortedByBalance = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when list is sorted and grouped then correct token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.sortedGroupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(
|
||||
statuses = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
isGrouped = flowOf(true.right()),
|
||||
isSortedByBalance = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens is empty then not initialized token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.notInitializedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(tokens = flowOf(emptySet<Token>().right()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks is empty and list is grouped then error should be received`() = runTest {
|
||||
val expectedResult = TokensError.EmptyNetworks.left()
|
||||
|
||||
val useCase = getUseCase(
|
||||
networks = emptySet<Network>().right(),
|
||||
isGrouped = flowOf(true.right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when tokens flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokensError.EmptyTokens.left()
|
||||
|
||||
val useCase = getUseCase(tokens = flowOf())
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokensError.EmptyNetworkStatues.left()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf())
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when networks statuses is empty then loading token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.loadingUngroupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(statuses = flowOf(emptySet<NetworkStatus>().right()))
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes flow is empty then error should be received`() = runTest {
|
||||
val expectedResult = TokensError.EmptyQuotes.left()
|
||||
|
||||
val useCase = getUseCase(quotes = flowOf())
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `when quotes is empty and statuses verified then loading token list should be received`() = runTest {
|
||||
val expectedResult = MockTokenLists.loadingUngroupedTokenList.right()
|
||||
|
||||
val useCase = getUseCase(
|
||||
statuses = flowOf(MockNetworks.verifiedNetworksStatuses.right()),
|
||||
quotes = flowOf(emptySet<Quote>().right()),
|
||||
)
|
||||
|
||||
// When
|
||||
val result = useCase(userWalletId).first()
|
||||
|
||||
// Then
|
||||
assertEquals(expectedResult, result)
|
||||
}
|
||||
|
||||
private fun getUseCase(
|
||||
tokens: Flow<Either<TokensError, Set<Token>>> = flowOf(MockTokens.tokens.right()),
|
||||
quotes: Flow<Either<TokensError, Set<Quote>>> = flowOf(MockQuotes.quotes.right()),
|
||||
networks: Either<TokensError, Set<Network>> = MockNetworks.networks.right(),
|
||||
statuses: Flow<Either<TokensError, Set<NetworkStatus>>> = flowOf(MockNetworks.errorNetworksStatuses.right()),
|
||||
isGrouped: Flow<Either<TokensError, Boolean>> = flowOf(MockTokenLists.isGrouped.right()),
|
||||
isSortedByBalance: Flow<Either<TokensError, Boolean>> = flowOf(MockTokenLists.isSortedByBalance.right()),
|
||||
) = GetTokenListUseCase(
|
||||
dispatchers = dispatchers,
|
||||
tokensRepository = MockTokensRepository(tokens, isGrouped, isSortedByBalance),
|
||||
quotesRepository = MockQuotesRepository(quotes),
|
||||
networksRepository = MockNetworksRepository(networks, statuses),
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.tangem.domain.tokens.mock
|
||||
|
||||
import arrow.core.NonEmptySet
|
||||
import arrow.core.nonEmptySetOf
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal object MockNetworks {
|
||||
|
||||
val amountToCreateAccount: BigDecimal = BigDecimal.TEN
|
||||
|
||||
val network1 = Network(
|
||||
id = Network.ID("network1"),
|
||||
name = "Network One",
|
||||
)
|
||||
|
||||
val network2 = Network(
|
||||
id = Network.ID("network2"),
|
||||
name = "Network Two",
|
||||
)
|
||||
|
||||
val network3 = Network(
|
||||
id = Network.ID("network3"),
|
||||
name = "Network Three",
|
||||
)
|
||||
|
||||
val networks = nonEmptySetOf(network1, network2, network3)
|
||||
|
||||
val networkStatus1 = NetworkStatus(
|
||||
networkId = network1.id,
|
||||
value = NetworkStatus.Unreachable,
|
||||
)
|
||||
|
||||
val networkStatus2 = NetworkStatus(
|
||||
networkId = network2.id,
|
||||
value = NetworkStatus.MissedDerivation,
|
||||
)
|
||||
|
||||
val networkStatus3 = NetworkStatus(
|
||||
networkId = network3.id,
|
||||
value = NetworkStatus.NoAccount(
|
||||
amountToCreateAccount = amountToCreateAccount,
|
||||
),
|
||||
)
|
||||
|
||||
val errorNetworksStatuses = nonEmptySetOf(networkStatus1, networkStatus2, networkStatus3)
|
||||
|
||||
val verifiedNetworkStatus1: NetworkStatus
|
||||
get() = networkStatus1.copy(
|
||||
value = NetworkStatus.Verified(
|
||||
amounts = mapOf(
|
||||
MockTokens.token1.id to BigDecimal.TEN,
|
||||
MockTokens.token2.id to BigDecimal.TEN,
|
||||
MockTokens.token3.id to BigDecimal.TEN,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val verifiedNetworkStatus2: NetworkStatus
|
||||
get() = networkStatus2.copy(
|
||||
value = NetworkStatus.Verified(
|
||||
amounts = mapOf(
|
||||
MockTokens.token4.id to BigDecimal.TEN,
|
||||
MockTokens.token5.id to BigDecimal.TEN,
|
||||
MockTokens.token6.id to BigDecimal.TEN,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val verifiedNetworkStatus3: NetworkStatus
|
||||
get() = networkStatus3.copy(
|
||||
value = NetworkStatus.Verified(
|
||||
amounts = mapOf(
|
||||
MockTokens.token7.id to BigDecimal.TEN,
|
||||
MockTokens.token8.id to BigDecimal.TEN,
|
||||
MockTokens.token9.id to BigDecimal.TEN,
|
||||
MockTokens.token10.id to BigDecimal.TEN,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
val verifiedNetworksStatuses: NonEmptySet<NetworkStatus>
|
||||
get() = nonEmptySetOf(
|
||||
verifiedNetworkStatus1,
|
||||
verifiedNetworkStatus2,
|
||||
verifiedNetworkStatus3,
|
||||
)
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
package com.tangem.domain.tokens.mock
|
||||
|
||||
import arrow.core.nonEmptySetOf
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal object MockQuotes {
|
||||
|
||||
val quote1 = Quote(
|
||||
tokenId = MockTokens.token1.id,
|
||||
fiatRate = BigDecimal("1.23"),
|
||||
priceChange = BigDecimal("0.01"),
|
||||
)
|
||||
|
||||
val quote2 = Quote(
|
||||
tokenId = MockTokens.token2.id,
|
||||
fiatRate = BigDecimal("2.34"),
|
||||
priceChange = BigDecimal("-0.02"),
|
||||
)
|
||||
|
||||
val quote3 = Quote(
|
||||
tokenId = MockTokens.token3.id,
|
||||
fiatRate = BigDecimal("3.45"),
|
||||
priceChange = BigDecimal("0.03"),
|
||||
)
|
||||
|
||||
val quote4 = Quote(
|
||||
tokenId = MockTokens.token4.id,
|
||||
fiatRate = BigDecimal("4.56"),
|
||||
priceChange = BigDecimal("-0.04"),
|
||||
)
|
||||
|
||||
val quote5 = Quote(
|
||||
tokenId = MockTokens.token5.id,
|
||||
fiatRate = BigDecimal("5.67"),
|
||||
priceChange = BigDecimal("0.05"),
|
||||
)
|
||||
|
||||
val quote6 = Quote(
|
||||
tokenId = MockTokens.token6.id,
|
||||
fiatRate = BigDecimal("6.78"),
|
||||
priceChange = BigDecimal("-0.06"),
|
||||
)
|
||||
|
||||
val quote7 = Quote(
|
||||
tokenId = MockTokens.token7.id,
|
||||
fiatRate = BigDecimal("7.89"),
|
||||
priceChange = BigDecimal("0.07"),
|
||||
)
|
||||
|
||||
val quote8 = Quote(
|
||||
tokenId = MockTokens.token8.id,
|
||||
fiatRate = BigDecimal("8.90"),
|
||||
priceChange = BigDecimal("-0.08"),
|
||||
)
|
||||
|
||||
val quote9 = Quote(
|
||||
tokenId = MockTokens.token9.id,
|
||||
fiatRate = BigDecimal("9.01"),
|
||||
priceChange = BigDecimal("0.09"),
|
||||
)
|
||||
|
||||
val quote10 = Quote(
|
||||
tokenId = MockTokens.token10.id,
|
||||
fiatRate = BigDecimal("10.12"),
|
||||
priceChange = BigDecimal("-0.10"),
|
||||
)
|
||||
|
||||
val quotes = nonEmptySetOf(quote1, quote2, quote3, quote4, quote5, quote6, quote7, quote8, quote9, quote10)
|
||||
}
|
||||
|
|
@ -0,0 +1,107 @@
|
|||
package com.tangem.domain.tokens.mock
|
||||
|
||||
import arrow.core.nonEmptySetOf
|
||||
import arrow.core.toNonEmptySetOrNull
|
||||
import com.tangem.domain.tokens.model.NetworkGroup
|
||||
import com.tangem.domain.tokens.model.TokenList
|
||||
import com.tangem.domain.tokens.model.TokenStatus
|
||||
import java.math.BigDecimal
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal object MockTokenLists {
|
||||
|
||||
const val isGrouped = false
|
||||
const val isSortedByBalance = false
|
||||
|
||||
val networkGroup1 = NetworkGroup(
|
||||
networkId = MockNetworks.network1.id,
|
||||
name = MockNetworks.network1.name,
|
||||
tokens = MockTokensStates.tokenStates
|
||||
.filter { it.networkId == MockNetworks.network1.id }
|
||||
.toNonEmptySetOrNull()!!,
|
||||
)
|
||||
|
||||
val networkGroup2 = NetworkGroup(
|
||||
networkId = MockNetworks.network2.id,
|
||||
name = MockNetworks.network2.name,
|
||||
tokens = MockTokensStates.tokenStates
|
||||
.filter { it.networkId == MockNetworks.network2.id }
|
||||
.toNonEmptySetOrNull()!!,
|
||||
)
|
||||
|
||||
val networkGroup3 = NetworkGroup(
|
||||
networkId = MockNetworks.network3.id,
|
||||
name = MockNetworks.network3.name,
|
||||
tokens = MockTokensStates.tokenStates
|
||||
.filter { it.networkId == MockNetworks.network3.id }
|
||||
.toNonEmptySetOrNull()!!,
|
||||
)
|
||||
|
||||
val networksGroups = nonEmptySetOf(networkGroup1, networkGroup2, networkGroup3)
|
||||
|
||||
val sortedNetworksGroups = networksGroups.map { group ->
|
||||
group.copy(
|
||||
tokens = MockTokensStates.loadedTokensStates
|
||||
.filter { it.networkId == group.networkId }
|
||||
.sortedByDescending { it.value.fiatAmount }
|
||||
.toNonEmptySetOrNull()!!,
|
||||
)
|
||||
}
|
||||
.sortedByDescending { group ->
|
||||
group.tokens.sumOf { it.value.fiatAmount!! }
|
||||
}
|
||||
.toNonEmptySetOrNull()!!
|
||||
|
||||
val notInitializedTokenList = TokenList.NotInitialized
|
||||
|
||||
val groupedTokenList = TokenList.GroupedByNetwork(
|
||||
groups = networksGroups,
|
||||
totalFiatBalance = TokenList.FiatBalance.Failed,
|
||||
sortedBy = TokenList.SortType.NONE,
|
||||
)
|
||||
|
||||
val ungroupedTokenList = TokenList.Ungrouped(
|
||||
tokens = MockTokensStates.tokenStates,
|
||||
totalFiatBalance = TokenList.FiatBalance.Failed,
|
||||
sortedBy = TokenList.SortType.NONE,
|
||||
)
|
||||
|
||||
val loadingUngroupedTokenList = with(ungroupedTokenList) {
|
||||
copy(
|
||||
tokens = tokens.map { it.copy(value = TokenStatus.Loading) },
|
||||
totalFiatBalance = TokenList.FiatBalance.Loading,
|
||||
)
|
||||
}
|
||||
|
||||
val sortedUngroupedTokenList: TokenList.Ungrouped
|
||||
get() {
|
||||
val tokens = MockTokensStates.loadedTokensStates
|
||||
.sortedByDescending { it.value.fiatAmount }
|
||||
.toNonEmptySetOrNull()!!
|
||||
|
||||
return ungroupedTokenList.copy(
|
||||
tokens = tokens,
|
||||
sortedBy = TokenList.SortType.BALANCE,
|
||||
totalFiatBalance = TokenList.FiatBalance.Loaded(
|
||||
amount = tokens.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO },
|
||||
isAllAmountsSummarized = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
val sortedGroupedTokenList: TokenList.GroupedByNetwork
|
||||
get() {
|
||||
val groups = sortedNetworksGroups
|
||||
|
||||
return groupedTokenList.copy(
|
||||
groups = groups,
|
||||
sortedBy = TokenList.SortType.BALANCE,
|
||||
totalFiatBalance = TokenList.FiatBalance.Loaded(
|
||||
amount = groups
|
||||
.flatMap { it.tokens }
|
||||
.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO },
|
||||
isAllAmountsSummarized = true,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
package com.tangem.domain.tokens.mock
|
||||
|
||||
import arrow.core.nonEmptySetOf
|
||||
import com.tangem.domain.tokens.model.Token
|
||||
|
||||
internal object MockTokens {
|
||||
|
||||
val token1 = Token(
|
||||
id = Token.ID("token1"),
|
||||
networkId = MockNetworks.network1.id,
|
||||
name = "Token 1",
|
||||
symbol = "T1",
|
||||
isCustom = false,
|
||||
isCoin = true,
|
||||
)
|
||||
val token2 = Token(
|
||||
id = Token.ID("token2"),
|
||||
networkId = MockNetworks.network1.id,
|
||||
name = "Token 2",
|
||||
symbol = "T2",
|
||||
isCustom = false,
|
||||
isCoin = false,
|
||||
)
|
||||
val token3 = Token(
|
||||
id = Token.ID("token3"),
|
||||
networkId = MockNetworks.network1.id,
|
||||
name = "Token 3",
|
||||
symbol = "T3",
|
||||
isCustom = false,
|
||||
isCoin = false,
|
||||
)
|
||||
val token4 = Token(
|
||||
id = Token.ID("token4"),
|
||||
networkId = MockNetworks.network2.id,
|
||||
name = "Token 4",
|
||||
symbol = "T4",
|
||||
isCustom = false,
|
||||
isCoin = true,
|
||||
)
|
||||
val token5 = Token(
|
||||
id = Token.ID("token5"),
|
||||
networkId = MockNetworks.network2.id,
|
||||
name = "Token 5",
|
||||
symbol = "T5",
|
||||
isCustom = false,
|
||||
isCoin = true,
|
||||
)
|
||||
val token6 = Token(
|
||||
id = Token.ID("token6"),
|
||||
networkId = MockNetworks.network2.id,
|
||||
name = "Token 6",
|
||||
symbol = "T6",
|
||||
isCustom = false,
|
||||
isCoin = false,
|
||||
)
|
||||
val token7 = Token(
|
||||
id = Token.ID("token7"),
|
||||
networkId = MockNetworks.network3.id,
|
||||
name = "Token 7",
|
||||
symbol = "T7",
|
||||
isCustom = false,
|
||||
isCoin = false,
|
||||
)
|
||||
val token8 = Token(
|
||||
id = Token.ID("token8"),
|
||||
networkId = MockNetworks.network3.id,
|
||||
name = "Token 8",
|
||||
symbol = "T8",
|
||||
isCustom = false,
|
||||
isCoin = true,
|
||||
)
|
||||
val token9 = Token(
|
||||
id = Token.ID("token9"),
|
||||
networkId = MockNetworks.network3.id,
|
||||
name = "Token 9",
|
||||
symbol = "T9",
|
||||
isCustom = false,
|
||||
isCoin = true,
|
||||
)
|
||||
val token10 = Token(
|
||||
id = Token.ID("token10"),
|
||||
networkId = MockNetworks.network3.id,
|
||||
name = "Token 10",
|
||||
symbol = "T10",
|
||||
isCustom = false,
|
||||
isCoin = false,
|
||||
)
|
||||
|
||||
val tokens = nonEmptySetOf(token1, token2, token3, token4, token5, token6, token7, token8, token9, token10)
|
||||
}
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
package com.tangem.domain.tokens.mock
|
||||
|
||||
import arrow.core.nonEmptySetOf
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.TokenStatus
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
internal object MockTokensStates {
|
||||
|
||||
val tokenState1 = TokenStatus(
|
||||
id = MockTokens.token1.id,
|
||||
networkId = MockTokens.token1.networkId,
|
||||
name = MockTokens.token1.name,
|
||||
symbol = MockTokens.token1.symbol,
|
||||
isCoin = MockTokens.token1.isCoin,
|
||||
value = TokenStatus.Unreachable,
|
||||
)
|
||||
|
||||
val tokenState2 = TokenStatus(
|
||||
id = MockTokens.token2.id,
|
||||
networkId = MockTokens.token2.networkId,
|
||||
name = MockTokens.token2.name,
|
||||
symbol = MockTokens.token2.symbol,
|
||||
isCoin = MockTokens.token2.isCoin,
|
||||
value = TokenStatus.Unreachable,
|
||||
)
|
||||
|
||||
val tokenState3 = TokenStatus(
|
||||
id = MockTokens.token3.id,
|
||||
networkId = MockTokens.token3.networkId,
|
||||
name = MockTokens.token3.name,
|
||||
symbol = MockTokens.token3.symbol,
|
||||
isCoin = MockTokens.token3.isCoin,
|
||||
value = TokenStatus.Unreachable,
|
||||
)
|
||||
|
||||
val tokenState4 = TokenStatus(
|
||||
id = MockTokens.token4.id,
|
||||
networkId = MockTokens.token4.networkId,
|
||||
name = MockTokens.token4.name,
|
||||
symbol = MockTokens.token4.symbol,
|
||||
isCoin = MockTokens.token4.isCoin,
|
||||
value = TokenStatus.MissedDerivation,
|
||||
)
|
||||
|
||||
val tokenState5 = TokenStatus(
|
||||
id = MockTokens.token5.id,
|
||||
networkId = MockTokens.token5.networkId,
|
||||
name = MockTokens.token5.name,
|
||||
symbol = MockTokens.token5.symbol,
|
||||
isCoin = MockTokens.token5.isCoin,
|
||||
value = TokenStatus.MissedDerivation,
|
||||
)
|
||||
|
||||
val tokenState6 = TokenStatus(
|
||||
id = MockTokens.token6.id,
|
||||
networkId = MockTokens.token6.networkId,
|
||||
name = MockTokens.token6.name,
|
||||
symbol = MockTokens.token6.symbol,
|
||||
isCoin = MockTokens.token6.isCoin,
|
||||
value = TokenStatus.MissedDerivation,
|
||||
)
|
||||
|
||||
val tokenState7 = TokenStatus(
|
||||
id = MockTokens.token7.id,
|
||||
networkId = MockTokens.token7.networkId,
|
||||
name = MockTokens.token7.name,
|
||||
symbol = MockTokens.token7.symbol,
|
||||
isCoin = MockTokens.token7.isCoin,
|
||||
value = TokenStatus.NoAccount,
|
||||
)
|
||||
|
||||
val tokenState8 = TokenStatus(
|
||||
id = MockTokens.token8.id,
|
||||
networkId = MockTokens.token8.networkId,
|
||||
name = MockTokens.token8.name,
|
||||
symbol = MockTokens.token8.symbol,
|
||||
isCoin = MockTokens.token8.isCoin,
|
||||
value = TokenStatus.NoAccount,
|
||||
)
|
||||
|
||||
val tokenState9 = TokenStatus(
|
||||
id = MockTokens.token9.id,
|
||||
networkId = MockTokens.token9.networkId,
|
||||
name = MockTokens.token9.name,
|
||||
symbol = MockTokens.token9.symbol,
|
||||
isCoin = MockTokens.token9.isCoin,
|
||||
value = TokenStatus.NoAccount,
|
||||
)
|
||||
|
||||
val tokenState10 = TokenStatus(
|
||||
id = MockTokens.token10.id,
|
||||
networkId = MockTokens.token10.networkId,
|
||||
name = MockTokens.token10.name,
|
||||
symbol = MockTokens.token10.symbol,
|
||||
isCoin = MockTokens.token10.isCoin,
|
||||
value = TokenStatus.NoAccount,
|
||||
)
|
||||
|
||||
val tokenStates = nonEmptySetOf(
|
||||
tokenState1,
|
||||
tokenState2,
|
||||
tokenState3,
|
||||
tokenState4,
|
||||
tokenState5,
|
||||
tokenState6,
|
||||
tokenState7,
|
||||
tokenState8,
|
||||
tokenState9,
|
||||
tokenState10,
|
||||
)
|
||||
|
||||
val loadedTokensStates = tokenStates.map { state ->
|
||||
val networkStatus = MockNetworks.verifiedNetworksStatuses.first { it.networkId == state.networkId }
|
||||
val amount = (networkStatus.value as NetworkStatus.Verified).amounts[state.id]!!
|
||||
val quote = MockQuotes.quotes.first { it.tokenId == state.id }
|
||||
val fiatAmount = amount * quote.fiatRate
|
||||
|
||||
state.copy(
|
||||
value = TokenStatus.Loaded(
|
||||
amount = amount,
|
||||
fiatAmount = fiatAmount,
|
||||
priceChange = quote.priceChange,
|
||||
hasTransactionsInProgress = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.TokensError
|
||||
import com.tangem.domain.tokens.model.Network
|
||||
import com.tangem.domain.tokens.model.NetworkStatus
|
||||
import com.tangem.domain.tokens.model.Token
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal class MockNetworksRepository(
|
||||
private val networks: Either<TokensError, Set<Network>>,
|
||||
private val statuses: Flow<Either<TokensError, Set<NetworkStatus>>>,
|
||||
) : NetworksRepository {
|
||||
|
||||
override fun getNetworks(networksIds: Set<Network.ID>): Either<TokensError, Set<Network>> {
|
||||
return networks
|
||||
}
|
||||
|
||||
override fun getNetworkStatuses(
|
||||
userWalletId: UserWalletId,
|
||||
networks: Map<Network.ID, Set<Token.ID>>,
|
||||
refresh: Boolean,
|
||||
): Flow<Either<TokensError, Set<NetworkStatus>>> {
|
||||
return statuses
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import com.tangem.domain.tokens.error.TokensError
|
||||
import com.tangem.domain.tokens.model.Quote
|
||||
import com.tangem.domain.tokens.model.Token
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal class MockQuotesRepository(
|
||||
private val quotes: Flow<Either<TokensError, Set<Quote>>>,
|
||||
) : QuotesRepository {
|
||||
|
||||
override fun getQuotes(tokensIds: Set<Token.ID>, refresh: Boolean): Flow<Either<TokensError, Set<Quote>>> {
|
||||
return quotes
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
package com.tangem.domain.tokens.repository
|
||||
|
||||
import arrow.core.Either
|
||||
import arrow.core.right
|
||||
import com.tangem.domain.tokens.error.TokensError
|
||||
import com.tangem.domain.tokens.model.Token
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
internal class MockTokensRepository(
|
||||
private val tokens: Flow<Either<TokensError, Set<Token>>>,
|
||||
private val isGrouped: Flow<Either<TokensError, Boolean>>,
|
||||
private val isSortedByBalance: Flow<Either<TokensError, Boolean>>,
|
||||
) : TokensRepository {
|
||||
|
||||
override suspend fun sortTokens(
|
||||
userWalletId: UserWalletId,
|
||||
sortedTokensIds: Set<Token.ID>,
|
||||
isGrouped: Boolean,
|
||||
isSortedByBalance: Boolean,
|
||||
): Either<TokensError, Unit> = Unit.right()
|
||||
|
||||
override fun getTokens(userWalletId: UserWalletId, refresh: Boolean): Flow<Either<TokensError, Set<Token>>> {
|
||||
return tokens
|
||||
}
|
||||
|
||||
override fun isTokensGrouped(userWalletId: UserWalletId): Flow<Either<TokensError, Boolean>> {
|
||||
return isGrouped
|
||||
}
|
||||
|
||||
override fun isTokensSortedByBalance(userWalletId: UserWalletId): Flow<Either<TokensError, Boolean>> {
|
||||
return isSortedByBalance
|
||||
}
|
||||
}
|
||||
|
|
@ -1,8 +1,9 @@
|
|||
package com.tangem.feature.wallet.presentation.common
|
||||
|
||||
import com.tangem.core.ui.R
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
import com.tangem.core.ui.components.transactions.TransactionState
|
||||
import com.tangem.feature.wallet.presentation.common.state.PriceChangeConfig
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
|
||||
import com.tangem.feature.wallet.presentation.organizetokens.DraggableItem
|
||||
|
|
@ -204,15 +205,6 @@ internal object WalletPreviewData {
|
|||
WalletManageButton.CopyAddress(onClick = {}),
|
||||
)
|
||||
|
||||
val marketplaceBlockContent = WalletMarketplaceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "0.11$",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "5.16%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
)
|
||||
|
||||
val multicurrencyWalletScreenState = WalletStateHolder.MultiCurrencyContent(
|
||||
onBackClick = {},
|
||||
topBarConfig = walletTopBarConfig,
|
||||
|
|
@ -300,6 +292,13 @@ internal object WalletPreviewData {
|
|||
),
|
||||
notifications = persistentListOf(WalletNotification.LikeTangemApp(onClick = {})),
|
||||
buttons = manageButtons,
|
||||
marketplaceBlockState = marketplaceBlockContent,
|
||||
marketPriceBlockState = MarketPriceBlockState.Content(
|
||||
currencyName = "BTC",
|
||||
price = "98900.12$",
|
||||
priceChangeConfig = PriceChangeConfig(
|
||||
valueInPercent = "5.16%",
|
||||
type = PriceChangeConfig.Type.UP,
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -28,11 +28,11 @@ import androidx.constraintlayout.compose.Dimension
|
|||
import coil.compose.SubcomposeAsyncImage
|
||||
import coil.request.ImageRequest
|
||||
import com.tangem.core.ui.components.*
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.res.TangemTypography
|
||||
import com.tangem.feature.wallet.impl.R
|
||||
import com.tangem.feature.wallet.presentation.common.WalletPreviewData
|
||||
import com.tangem.feature.wallet.presentation.common.state.PriceChangeConfig
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState
|
||||
import com.tangem.feature.wallet.presentation.common.state.TokenItemState.TokenOptionsState
|
||||
import org.burnoutcrew.reorderable.ReorderableLazyListState
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.common.state
|
||||
|
||||
/**
|
||||
* Price changing config
|
||||
*
|
||||
* @property valueInPercent value in percent
|
||||
* @property type type [Type]
|
||||
*/
|
||||
internal data class PriceChangeConfig(val valueInPercent: String, val type: Type) {
|
||||
|
||||
/** Price changing type */
|
||||
enum class Type {
|
||||
UP, DOWN
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.feature.wallet.presentation.common.state
|
|||
|
||||
import androidx.annotation.DrawableRes
|
||||
import androidx.compose.runtime.Immutable
|
||||
import com.tangem.core.ui.components.marketprice.PriceChangeConfig
|
||||
|
||||
/** Token item state */
|
||||
@Immutable
|
||||
|
|
|
|||
|
|
@ -1,33 +0,0 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state
|
||||
|
||||
import com.tangem.feature.wallet.presentation.common.state.PriceChangeConfig
|
||||
|
||||
/**
|
||||
* Wallet marketplace component state
|
||||
*
|
||||
* @property currencyName currency name
|
||||
*
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
internal sealed class WalletMarketplaceBlockState(open val currencyName: String) {
|
||||
|
||||
/**
|
||||
* Loading state
|
||||
*
|
||||
* @property currencyName currency name
|
||||
*/
|
||||
data class Loading(override val currencyName: String) : WalletMarketplaceBlockState(currencyName = currencyName)
|
||||
|
||||
/**
|
||||
* Content state
|
||||
*
|
||||
* @property currencyName currency name
|
||||
* @property price price
|
||||
* @property priceChangeConfig price change config
|
||||
*/
|
||||
data class Content(
|
||||
override val currencyName: String,
|
||||
val price: String,
|
||||
val priceChangeConfig: PriceChangeConfig,
|
||||
) : WalletMarketplaceBlockState(currencyName = currencyName)
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.feature.wallet.presentation.wallet.state
|
||||
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlockState
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
|
||||
/**
|
||||
|
|
@ -49,7 +50,7 @@ internal sealed class WalletStateHolder(
|
|||
* @property contentItems content items
|
||||
* @property notifications notifications
|
||||
* @property buttons manage buttons
|
||||
* @property marketplaceBlockState marketplace block state
|
||||
* @property marketPriceBlockState market price block state
|
||||
*/
|
||||
data class SingleCurrencyContent(
|
||||
override val onBackClick: () -> Unit,
|
||||
|
|
@ -58,6 +59,6 @@ internal sealed class WalletStateHolder(
|
|||
override val contentItems: ImmutableList<WalletContentItemState.SingleCurrencyItem>,
|
||||
override val notifications: ImmutableList<WalletNotification>,
|
||||
val buttons: ImmutableList<WalletManageButton>,
|
||||
val marketplaceBlockState: WalletMarketplaceBlockState,
|
||||
val marketPriceBlockState: MarketPriceBlockState,
|
||||
) : WalletStateHolder(onBackClick, topBarConfig, walletsListConfig, contentItems, notifications)
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.tooling.preview.datasource.CollectionPreviewParameterProvider
|
||||
import com.tangem.core.ui.components.buttons.actions.ActionButtonConfig
|
||||
import com.tangem.core.ui.components.buttons.actions.RoundedActionButton
|
||||
import com.tangem.core.ui.components.marketprice.MarketPriceBlock
|
||||
import com.tangem.core.ui.components.notifications.Notification
|
||||
import com.tangem.core.ui.components.transactions.Transaction
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -33,7 +34,6 @@ import com.tangem.feature.wallet.presentation.wallet.ui.components.WalletsList
|
|||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TransactionsBlockGroupTitle
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.TransactionsBlockTitle
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.WalletManageButtons
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.components.singlecurrency.WalletMarketplaceBlock
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.decorations.walletContentItemDecoration
|
||||
import com.tangem.feature.wallet.presentation.wallet.ui.utils.changeWalletAnimator
|
||||
|
||||
|
|
@ -94,8 +94,8 @@ internal fun WalletScreen(state: WalletStateHolder) {
|
|||
|
||||
if (state is WalletStateHolder.SingleCurrencyContent) {
|
||||
item {
|
||||
WalletMarketplaceBlock(
|
||||
state = state.marketplaceBlockState,
|
||||
MarketPriceBlock(
|
||||
state = state.marketPriceBlockState,
|
||||
modifier = changeableItemModifier
|
||||
.padding(top = TangemTheme.dimens.spacing14)
|
||||
.padding(horizontal = TangemTheme.dimens.spacing16),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue