From 9b95a705904ac4907dabb03aa5d87be051eddb5d Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 20:21:04 +0300 Subject: [PATCH 01/25] Updated on 2026-08-14 --- gradle/dependencies.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index c009175e70..ecddaa6a11 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,9 +89,9 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "develop-775" +tangemBlockchainSdk = "release-app_5.15-776" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds -tangemCardSdk = "develop-381" +tangemCardSdk = "release-app_5.15-382" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ tangemVico = "2.0.0-alpha.25-tangem16" #tangemVico = "0.0.1" # Keep it! - used for local builds ^ From 67fbc262624b6af530e6f5c1ac9a42b521cc7465 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 23:18:18 +0300 Subject: [PATCH 02/25] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 5a8e078bec..da5171abe7 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -88,7 +88,7 @@ markdown = "0.7.2" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.14-772" +tangemBlockchainSdk = "release-app_5.14-777" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.14-379" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From d3cb89b1a1fd0bfef454649717c2c6b1e1e783bd Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 22:31:40 +0300 Subject: [PATCH 03/25] Updated on 2026-08-14 --- .../src/main/java/com/tangem/pagination/BatchListSource.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/pagination/src/main/java/com/tangem/pagination/BatchListSource.kt b/core/pagination/src/main/java/com/tangem/pagination/BatchListSource.kt index db1c27bbbc..535c7deea4 100644 --- a/core/pagination/src/main/java/com/tangem/pagination/BatchListSource.kt +++ b/core/pagination/src/main/java/com/tangem/pagination/BatchListSource.kt @@ -99,7 +99,7 @@ private class DefaultBatchListSource scope.launch { context.actionsFlow - .conflate() + .buffer() .collect { action -> collectActions(action) } From a94db85dfdd5624456d0778ce18c75aec7edf87f Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 22:34:07 +0300 Subject: [PATCH 04/25] Updated on 2026-08-14 --- .../api/tangemTech/TangemTechApi.kt | 9 +++++++ .../markets/DefaultMarketsTokenRepository.kt | 27 +++++++++++++------ .../com/tangem/domain/markets/TokenQuotes.kt | 15 ++++++++++- .../tangem/domain/markets/TokenQuotesShort.kt | 11 ++++++++ .../markets/GetTokenFullQuotesUseCase.kt | 7 ++++- .../repositories/MarketsTokenRepository.kt | 2 +- .../impl/model/MarketsTokenDetailsModel.kt | 7 +++-- 7 files changed, 65 insertions(+), 13 deletions(-) diff --git a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt index 23edacd61b..4a52e5d13e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/api/tangemTech/TangemTechApi.kt @@ -135,4 +135,13 @@ interface TangemTechApi { @ReadTimeout(duration = 5, unit = TimeUnit.SECONDS) @GET("networks/providers") suspend fun getBlockchainProviders(): Map> + + companion object { + val marketsQuoteFields = listOf( + "price", + "priceChange24h", + "priceChange1w", + "priceChange30d", + ) + } } \ No newline at end of file diff --git a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt index 39637200e5..79576d75c3 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/DefaultMarketsTokenRepository.kt @@ -9,14 +9,17 @@ import com.tangem.data.common.currency.CryptoCurrencyFactory import com.tangem.data.common.currency.getNetwork import com.tangem.data.common.utils.retryOnError import com.tangem.data.markets.analytics.MarketsDataAnalyticsEvent +import com.tangem.data.markets.converters.* import com.tangem.data.markets.converters.TokenChartConverter import com.tangem.data.markets.converters.TokenMarketInfoConverter import com.tangem.data.markets.converters.TokenMarketListConverter +import com.tangem.data.markets.converters.TokenQuotesShortConverter import com.tangem.data.markets.converters.toRequestParam import com.tangem.datasource.api.common.response.ApiResponseError import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.TangemTechApi.Companion.marketsQuoteFields import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.common.util.derivationStyleProvider import com.tangem.domain.markets.* @@ -188,16 +191,24 @@ internal class DefaultMarketsTokenRepository( return TokenMarketInfoConverter.convert(resultResponse) } - override suspend fun getTokenQuotes(fiatCurrencyCode: String, tokenId: String): TokenQuotes { - // TODO change method when backend is ready - // add error analytics event - val response = marketsApi.getCoinMarketData( - currency = fiatCurrencyCode, - coinId = tokenId, - language = "en", + override suspend fun getTokenQuotes(fiatCurrencyCode: String, tokenId: String, tokenSymbol: String): TokenQuotes { + // for second markets iteration we should use extended api method with all required fields + val response = tangemTechApi.getQuotes( + currencyId = fiatCurrencyCode, + coinIds = tokenId, + fields = marketsQuoteFields.joinToString(separator = ","), ) - return TokenMarketInfoConverter.convert(response.getOrThrow()).quotes + val result = catchApiErrorAndSendEvent( + errorEvent = MarketsDataAnalyticsEvent.Details.Error( + request = MarketsDataAnalyticsEvent.Details.Error.Request.Info, + tokenSymbol = tokenSymbol, + ), + ) { + response.getOrThrow() + } + + return TokenQuotesShortConverter.convert(tokenId, result).toFull() } override suspend fun createCryptoCurrency( diff --git a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotes.kt b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotes.kt index 18826801e3..56bd39c7c1 100644 --- a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotes.kt +++ b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotes.kt @@ -11,4 +11,17 @@ data class TokenQuotes( val m6ChangePercent: BigDecimal?, val yearChangePercent: BigDecimal?, val allTimeChangePercent: BigDecimal?, -) \ No newline at end of file +) + +fun TokenQuotes.populateWith(quotes: TokenQuotes): TokenQuotes { + return TokenQuotes( + currentPrice = quotes.currentPrice, + h24ChangePercent = quotes.h24ChangePercent ?: this.h24ChangePercent, + weekChangePercent = quotes.weekChangePercent ?: this.weekChangePercent, + monthChangePercent = quotes.monthChangePercent ?: this.monthChangePercent, + m3ChangePercent = quotes.m3ChangePercent ?: this.m3ChangePercent, + m6ChangePercent = quotes.m6ChangePercent ?: this.m6ChangePercent, + yearChangePercent = quotes.yearChangePercent ?: this.yearChangePercent, + allTimeChangePercent = quotes.allTimeChangePercent ?: this.allTimeChangePercent, + ) +} \ No newline at end of file diff --git a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotesShort.kt b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotesShort.kt index 3b6bb3bdf1..ce2ff4bb71 100644 --- a/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotesShort.kt +++ b/domain/markets/models/src/main/kotlin/com/tangem/domain/markets/TokenQuotesShort.kt @@ -7,4 +7,15 @@ data class TokenQuotesShort( val h24ChangePercent: BigDecimal, val weekChangePercent: BigDecimal, val monthChangePercent: BigDecimal, +) + +fun TokenQuotesShort.toFull() = TokenQuotes( + currentPrice = currentPrice, + h24ChangePercent = h24ChangePercent, + weekChangePercent = weekChangePercent, + monthChangePercent = monthChangePercent, + m3ChangePercent = null, + m6ChangePercent = null, + yearChangePercent = null, + allTimeChangePercent = null, ) \ No newline at end of file diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/GetTokenFullQuotesUseCase.kt b/domain/markets/src/main/java/com/tangem/domain/markets/GetTokenFullQuotesUseCase.kt index a755057a98..e8b8470add 100644 --- a/domain/markets/src/main/java/com/tangem/domain/markets/GetTokenFullQuotesUseCase.kt +++ b/domain/markets/src/main/java/com/tangem/domain/markets/GetTokenFullQuotesUseCase.kt @@ -7,11 +7,16 @@ import com.tangem.domain.markets.repositories.MarketsTokenRepository class GetTokenFullQuotesUseCase( private val marketsTokenRepository: MarketsTokenRepository, ) { - suspend operator fun invoke(appCurrency: AppCurrency, tokenId: String): Either { + suspend operator fun invoke( + appCurrency: AppCurrency, + tokenId: String, + tokenSymbol: String, + ): Either { return Either.catch { marketsTokenRepository.getTokenQuotes( fiatCurrencyCode = appCurrency.code, tokenId = tokenId, + tokenSymbol = tokenSymbol, ) }.mapLeft {} } diff --git a/domain/markets/src/main/java/com/tangem/domain/markets/repositories/MarketsTokenRepository.kt b/domain/markets/src/main/java/com/tangem/domain/markets/repositories/MarketsTokenRepository.kt index c9ff5dae64..f28da22c7b 100644 --- a/domain/markets/src/main/java/com/tangem/domain/markets/repositories/MarketsTokenRepository.kt +++ b/domain/markets/src/main/java/com/tangem/domain/markets/repositories/MarketsTokenRepository.kt @@ -33,7 +33,7 @@ interface MarketsTokenRepository { languageCode: String, ): TokenMarketInfo - suspend fun getTokenQuotes(fiatCurrencyCode: String, tokenId: String): TokenQuotes + suspend fun getTokenQuotes(fiatCurrencyCode: String, tokenId: String, tokenSymbol: String): TokenQuotes suspend fun createCryptoCurrency( userWalletId: UserWalletId, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt index 5f12f70b59..647c40534c 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/details/impl/model/MarketsTokenDetailsModel.kt @@ -229,6 +229,7 @@ internal class MarketsTokenDetailsModel @Inject constructor( val result = getTokenFullQuotesUseCase( tokenId = params.token.id, appCurrency = currentAppCurrency.value, + tokenSymbol = params.token.symbol, ) result.onRight { res -> @@ -389,9 +390,11 @@ internal class MarketsTokenDetailsModel @Inject constructor( } private suspend fun updateQuotes(newQuotes: TokenQuotes) { - quotesStateUpdater.updateQuotes(newQuotes) + val populatedNewQuotes = currentQuotes.value.populateWith(newQuotes) - val percent = newQuotes + quotesStateUpdater.updateQuotes(newQuotes = populatedNewQuotes) + + val percent = populatedNewQuotes .getPercentByInterval(interval = state.value.selectedInterval) chartDataProducer.runTransaction { From 648ceb99462d81e455f7fdc279397de336bdb3a5 Mon Sep 17 00:00:00 2001 From: Tangem Date: Mon, 16 Sep 2024 22:35:36 +0300 Subject: [PATCH 05/25] Updated on 2026-08-14 --- .../ui/components/list/InfiniteListHandler.kt | 19 ++++- .../data/markets/MarketsBatchUpdateFetcher.kt | 12 +-- .../statemanager/MarketsListUMStateManager.kt | 77 ++++++++++--------- .../markets/tokenlist/impl/ui/MarketsList.kt | 3 +- .../ui/components/MarketsListLazyColumn.kt | 12 ++- .../MarketChartListItemPreviewDataProvider.kt | 6 ++ .../impl/ui/state/MarketsListItemUM.kt | 2 +- .../tokenlist/impl/ui/state/MarketsListUM.kt | 3 +- .../presentation/wallet/ui/WalletScreen.kt | 20 ++++- 9 files changed, 94 insertions(+), 60 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt b/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt index 9d5c548b93..8f5f5ba4b7 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/list/InfiniteListHandler.kt @@ -4,8 +4,13 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.* @Composable -fun InfiniteListHandler(listState: LazyListState, onLoadMore: () -> Boolean, buffer: Int = 2) { - val loadMore by remember { +fun InfiniteListHandler( + listState: LazyListState, + onLoadMore: () -> Boolean, + buffer: Int = 2, + triggerLoadMoreCheckOnItemsCountChange: Boolean = false, +) { + val loadMore by remember(buffer, listState) { derivedStateOf { val layoutInfo = listState.layoutInfo val totalItemsNumber = layoutInfo.totalItemsCount @@ -15,12 +20,18 @@ fun InfiniteListHandler(listState: LazyListState, onLoadMore: () -> Boolean, buf } } - val totalItemsCount by remember { derivedStateOf { listState.layoutInfo.totalItemsCount } } - var emitted by remember(totalItemsCount) { mutableStateOf(false) } + val totalItemsCount by remember(listState) { derivedStateOf { listState.layoutInfo.totalItemsCount } } + var emitted by remember(totalItemsCount, buffer, listState) { mutableStateOf(false) } LaunchedEffect(loadMore) { if (loadMore && !emitted) { emitted = onLoadMore() } } + + LaunchedEffect(totalItemsCount) { + if (triggerLoadMoreCheckOnItemsCountChange && loadMore && !emitted) { + emitted = onLoadMore() + } + } } \ No newline at end of file diff --git a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt index 95fb2cca25..18c7155b03 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/MarketsBatchUpdateFetcher.kt @@ -9,6 +9,7 @@ import com.tangem.datasource.api.common.response.getOrThrow import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.markets.models.response.TokenMarketChartListResponse import com.tangem.datasource.api.tangemTech.TangemTechApi +import com.tangem.datasource.api.tangemTech.TangemTechApi.Companion.marketsQuoteFields import com.tangem.domain.markets.TokenMarket import com.tangem.domain.markets.TokenMarketUpdateRequest import com.tangem.pagination.Batch @@ -70,7 +71,7 @@ internal class MarketsBatchUpdateFetcher( tangemTechApi.getQuotes( currencyId = updateRequest.currencyId, coinIds = idsToUpdate.map { it.second }.flatten().joinToString(separator = ","), - fields = quoteFields.joinToString(separator = ","), + fields = marketsQuoteFields.joinToString(separator = ","), ).getOrThrow() } } @@ -120,13 +121,4 @@ internal class MarketsBatchUpdateFetcher( throw e } } - - companion object { - private val quoteFields = listOf( - "price", - "priceChange24h", - "priceChange1w", - "priceChange30d", - ) - } } \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt index f22b26c622..65d8c2df96 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/model/statemanager/MarketsListUMStateManager.kt @@ -14,7 +14,6 @@ import com.tangem.features.markets.tokenlist.impl.ui.state.MarketsListUM import com.tangem.features.markets.tokenlist.impl.ui.state.SortByTypeUM import com.tangem.utils.Provider import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.flow.* @@ -111,54 +110,55 @@ internal class MarketsListUMStateManager( private fun MarketsListUM.updateItems(newItems: ImmutableList): MarketsListUM { val currentState = this - val isNextPageInSearch = isInSearchState && (this.list as? ListUM.Content)?.showUnder100kTokens == true - var searchUiItemsCached: ImmutableList = persistentListOf() - val items = when { - isInSearchState && isNextPageInSearch.not() -> { - searchUiItemsCached = newItems - val filtered = newItems.filter { item -> item.isUnder100kMarketCap.not() }.toImmutableList() + if (isInSearchMode.not() || currentState.showUnder100kButtonAlreadyPressed()) { + val itemsWithFilteredPriceChange = newItems.filterPriceChangeByVisibility() - if (filtered.size == newItems.size) { - return currentState.copy(list = generalContentState(newItems)) - } else { - filtered - } - } - else -> { - searchUiItemsCached = persistentListOf() - newItems - } + return currentState.copy( + list = generalContentState(itemsWithFilteredPriceChange) + .copy( + showUnder100kTokensNotificationWasHidden = currentState.showUnder100kButtonAlreadyPressed(), + ), + ) } - val itemsWithFilteredPriceChange = items.filterPriceChangeByVisibility() + // Search state cases - return currentState.copy( - list = ListUM.Content( - items = itemsWithFilteredPriceChange, - loadMore = onLoadMoreUiItems, - visibleIdsChanged = visibleItemsChanged, - showUnder100kTokens = isInSearchState.not() || isNextPageInSearch, - onShowTokensUnder100kClicked = { - if (searchUiItemsCached.isNotEmpty()) { + val filtered = newItems.filter { item -> item.isUnder100kMarketCap.not() } + .toImmutableList() + .filterPriceChangeByVisibility() + + if (filtered.size != newItems.size) { + val searchUiItemsCached = newItems.filterPriceChangeByVisibility() + + return currentState.copy( + list = generalContentState(filtered).copy( + showUnder100kTokensNotificationWasHidden = false, + showUnder100kTokensNotification = true, + onShowTokensUnder100kClicked = { state.update { s -> - if (s.list is ListUM.Content) { + (s.list as? ListUM.Content)?.let { s.copy( list = s.list.copy( items = searchUiItemsCached, - showUnder100kTokens = true, + showUnder100kTokensNotification = false, + showUnder100kTokensNotificationWasHidden = true, ), ) - } else { - s - } + } ?: s } - } - }, - triggerScrollReset = consumedEvent(), - onItemClick = onTokenClick, - ), - ) + }, + ), + ) + } else { + return currentState.copy( + list = generalContentState(newItems.filterPriceChangeByVisibility()), + ) + } + } + + private fun MarketsListUM.showUnder100kButtonAlreadyPressed(): Boolean { + return this.list is ListUM.Content && this.isInSearchMode && this.list.showUnder100kTokensNotificationWasHidden } // Show price change animation for visible items only @@ -182,10 +182,11 @@ internal class MarketsListUMStateManager( items = newItems, loadMore = onLoadMoreUiItems, visibleIdsChanged = visibleItemsChanged, - showUnder100kTokens = true, + showUnder100kTokensNotification = false, onShowTokensUnder100kClicked = {}, triggerScrollReset = consumedEvent(), onItemClick = onTokenClick, + showUnder100kTokensNotificationWasHidden = false, ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt index 9c52cb6bdb..6847621b60 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/MarketsList.kt @@ -301,7 +301,8 @@ private fun Preview() { item.copy(id = index.toString()) } .toImmutableList(), - showUnder100kTokens = false, + showUnder100kTokensNotification = false, + showUnder100kTokensNotificationWasHidden = false, loadMore = {}, visibleIdsChanged = {}, onShowTokensUnder100kClicked = {}, diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt index 5d70d6e85e..f4dd833503 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/components/MarketsListLazyColumn.kt @@ -22,6 +22,7 @@ import com.tangem.features.markets.tokenlist.impl.ui.state.ListUM import kotlinx.coroutines.launch private const val LOAD_NEXT_PAGE_ON_END_INDEX = 50 +private const val LOAD_NEXT_PAGE_ON_END_INDEX_SEARCH = 25 private const val TOKEN_LAZY_LIST_ID_SEPARATOR = "***" @Composable @@ -95,7 +96,7 @@ internal fun MarketsListLazyColumn( ) } - if (isInSearchMode && state.showUnder100kTokens.not()) { + if (isInSearchMode && state.showUnder100kTokensNotification) { item(key = "show tokens under 100k".hashCode()) { ShowTokensUnder100kItem( onShowTokensClick = state.onShowTokensUnder100kClicked, @@ -112,10 +113,15 @@ internal fun MarketsListLazyColumn( InfiniteListHandler( listState = lazyListState, - buffer = LOAD_NEXT_PAGE_ON_END_INDEX, + buffer = if (isInSearchMode) { + LOAD_NEXT_PAGE_ON_END_INDEX_SEARCH + } else { + LOAD_NEXT_PAGE_ON_END_INDEX + }, + triggerLoadMoreCheckOnItemsCountChange = true, onLoadMore = remember(state) { { - if (state is ListUM.Content && state.showUnder100kTokens) { + if (state is ListUM.Content && state.showUnder100kTokensNotification.not()) { state.loadMore() true } else { diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt index 41d1596f68..e0c4a52d54 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/preview/MarketChartListItemPreviewDataProvider.kt @@ -22,6 +22,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -34,6 +35,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet trendPercentText = "12.43%", trendType = PriceChangeType.NEUTRAL, chardData = null, + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -48,6 +50,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -62,6 +65,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -76,6 +80,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), MarketsListItemUM( id = "1", @@ -90,6 +95,7 @@ internal class MarketChartListItemPreviewDataProvider : CollectionPreviewParamet chardData = MarketChartRawData( y = persistentListOf(0.4, 0.2, 0.4, 0.1, 0.4, 2.0, 5.0, 0.1, 2.0, 2.0, 3.0), ), + isUnder100kMarketCap = false, ), ), ) \ No newline at end of file diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt index 9f3821c9c5..9bc808aee8 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListItemUM.kt @@ -17,7 +17,7 @@ data class MarketsListItemUM( val trendPercentText: String, val trendType: PriceChangeType, val chardData: MarketChartRawData?, - val isUnder100kMarketCap: Boolean = false, + val isUnder100kMarketCap: Boolean, ) { val chartType: MarketChartLook.Type = when (trendType) { PriceChangeType.UP -> MarketChartLook.Type.Growing diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt index 7906cc1fb9..10ed82175e 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/tokenlist/impl/ui/state/MarketsListUM.kt @@ -41,7 +41,8 @@ sealed class ListUM { data class Content( val items: ImmutableList, - val showUnder100kTokens: Boolean, + val showUnder100kTokensNotification: Boolean, + val showUnder100kTokensNotificationWasHidden: Boolean, val loadMore: () -> Unit, val visibleIdsChanged: (List) -> Unit, val onShowTokensUnder100kClicked: () -> Unit, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index fc8d3b6572..7243dbb143 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -462,7 +462,9 @@ private inline fun BaseScaffoldWithMarkets( color = BottomSheetDefaults.ScrimColor, visible = bottomSheetState.targetValue == TangemSheetValue.Expanded || state.showMarketsOnboarding, - onDismissRequest = { coroutineScope.launch { bottomSheetState.partialExpand() } }, + onDismissRequest = { + coroutineScope.launch { bottomSheetState.partialExpand() } + }, ) MarketsTooltip( @@ -486,7 +488,6 @@ private inline fun BaseScaffoldWithMarkets( } } -@OptIn(ExperimentalMaterial3Api::class) @Composable private fun MarketsTooltip( availableHeight: Dp, @@ -644,6 +645,21 @@ private fun BottomSheetStateEffects( val systemUiController = rememberSystemUiController() val navigationBarColor = TangemTheme.colors.background.primary + LaunchedEffect(Unit) { + delay(timeMillis = 100) + when (bottomSheetState.currentValue) { + TangemSheetValue.Hidden, + TangemSheetValue.Expanded, + -> systemUiController.setNavigationBarColor( + color = Color.Transparent, + darkIcons = navigationBarColor.luminance() > 0.5f, + navigationBarContrastEnforced = true, + ) + TangemSheetValue.PartiallyExpanded, + -> systemUiController.setNavigationBarColor(navigationBarColor) + } + } + LaunchedEffect(key1 = bottomSheetState.targetValue, navigationBarColor) { when (bottomSheetState.targetValue) { TangemSheetValue.Hidden, From 301c0081bd40e224227807a30bce944771f05061 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 12:19:29 +0300 Subject: [PATCH 06/25] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index aa10d5bb23..cb4e3722a1 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.14-777" +tangemBlockchainSdk = "release-app_5.15-778" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.15-382" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 6f563747437340b4384c0e1da11c1b522ffe3bdd Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 14:43:19 +0500 Subject: [PATCH 07/25] Updated on 2026-08-14 --- .../factory/TokenDetailsBalanceSelectStateConverter.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt index 7695aa744c..0625d38565 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsBalanceSelectStateConverter.kt @@ -2,6 +2,7 @@ package com.tangem.feature.tokendetails.presentation.tokendetails.state.factory import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.domain.appcurrency.model.AppCurrency +import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.tokens.model.CryptoCurrencyStatus import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance @@ -20,8 +21,9 @@ internal class TokenDetailsBalanceSelectStateConverter( if (stakingBlocksState !is StakingBlockUM.Staked) return this val cryptoCurrencyStatus = cryptoCurrencyStatusProvider() ?: return this - val stakingCryptoAmount = stakingBlocksState.cryptoAmount - val stakingFiatAmount = stakingBlocksState.fiatAmount + val yieldBalance = cryptoCurrencyStatus.value.yieldBalance as? YieldBalance.Data + val stakingCryptoAmount = yieldBalance?.getTotalWithRewardsStakingBalance() + val stakingFiatAmount = stakingCryptoAmount?.let { cryptoCurrencyStatus.value.fiatRate?.multiply(it) } copy( tokenBalanceBlockState = if (tokenBalanceBlockState is TokenDetailsBalanceBlockState.Content) { From dc5becd3c5fe3a58dc500b4941f6efcaf44f0aa6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 14:43:36 +0500 Subject: [PATCH 08/25] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 6 +++ core/res/src/main/res/values-ja/strings.xml | 4 ++ core/res/src/main/res/values-ru/strings.xml | 2 + .../src/main/res/values-uk-rUA/strings.xml | 21 +++++---- core/res/src/main/res/values/strings.xml | 8 +++- .../SetInitialDataStateTransformer.kt | 46 ++++++++++++------- 6 files changed, 61 insertions(+), 26 deletions(-) diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index ef2d858a71..c130e68816 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -650,6 +650,8 @@ Die Anzahl der zu stakenden Krypros muss mindesten %s betragen Der Stakingbetrag wird aufgrund der Netzwerkregeln auf %1$s TRX aufgerundet. Nicht gestakte beanspruche + Gebühr für das Staking-Konto + Ein Staking-Konto ist ein spezielles Konto, auf dem eingesetzte SOL-Token gelagert werden. Es wird erstellt, wenn du deine Token an einen Validator delegierst, um an der Transaktionsvalidierung teilzunehmen und Belohnungen zu verdienen. Für die Erstellung des Staking-Kontos wird eine geringe Gebühr erhoben, die nach Abschluss des Stakings zurückgegeben wird. Jährliche prozentuale Rendite Die jährliche prozentuale Rendite, die du durch die Teilnahme am Staking erzielen kannst. Effektiver Jahreszins @@ -705,6 +707,7 @@ Block Tag Täglich + Jeder %1$s Epoche Ära Stunde @@ -721,6 +724,7 @@ Die Transaktion wird bearbeitet! Derzeit findet eine Validierung in der Blockchain statt. Dies kann einige Minuten dauern. Lösen der Bindungen Gelocktes unlocken + Entsperren Unstaken Staking beenden Unstake Assets %s @@ -863,6 +867,8 @@ Aktivierungsfehler Laut den Entwicklern des BNB-Netzes wird die Unterstützung für den BEP-2-Standard im Juni 2024 enden. Um den Verlust von Vermögenswerten mit diesem Standard zu vermeiden, konvertiere bitte in den BEP-20 Standard. Nutze gerne unseren Swap-Service, um sie auf das BNB Smart Chain Netzwerk zu übertragen. BNB Beacon Chain wird abgeschaltet + Bitte zahle ein paar %1$s ein, um die Netzwerkgebühr zu decken + Unzureichende Mittel zur Deckung der Netzgebühr Ausbaufähig Gefällt mir OK, habe ich verstanden! diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index ace34d86b3..1a848e9582 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -640,6 +640,8 @@ ステーキング金額は %s 以上である必要があります ネットワークルールにより、ステーキング金額は%1$s TRX に切り上げられます。 ステーキング解除分を請求する + ステーキングアカウント手数料 + ステーキングアカウントは、ステーキングされたSOLトークンが保管される特別なアカウントです。取引の検証に参加して報酬を得るために、トークンをバリデーターに委任すると、このアカウントが作成されます。ステーキングアカウントの作成には少額の手数料がかかりますが、この手数料はステーキングが完了すると返金されます。 年率 ステーキングに参加することで得られる年間収益率。 APR @@ -695,6 +697,7 @@ ブロック 毎日 + %1$s毎 エポック 時代 @@ -711,6 +714,7 @@ 取引を処理中です。現在、ブロックチェーンで検証が行われています。これには数分かかる場合があります。 ステーキング解約中 ロック解除 + ロック解除中 ステーキングされていない ステーキング解除 ステーキング解除中の資産%s diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index fff0190f6d..6ffdadf52b 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -654,6 +654,7 @@ Имя Сумма для стейкинга должна быть не менее %s Забрать средства + Стейкинг аккаунт — это специальный счет, на котором хранятся застейканные токены SOL. Он создается при делегировании ваших токенов валидатору для участия в подтверждении транзакций и получении наград. За создание стейкинг аккаунта взимается небольшая комиссия, которая возвращается после завершения стейкинга. Процентная ставка Годовой процентный доход, который вы можете получить от участия в стейкинге. APR @@ -697,6 +698,7 @@ Блок День Каждый день + Каждые ~%1$s сек Эпоха Эра Час diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 9ef0e3fb24..9e4b55bc64 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -120,7 +120,7 @@ Перейти до провайдера Перейти до токену Імпортувати - процесі + В процесі Пізніше Залишилося %1$s Заблокований @@ -357,6 +357,7 @@ Моє портфоліо Маркет Щоб згенерувати адреси для обраних мереж, потрібно відсканувати свою картку Tangem + Щоб додати токени, потягніть вгору або торкніться панелі пошуку Дані цього розділу отримані з наступних мереж: %s Не вдалося завантажити дані... Немає даних @@ -367,13 +368,13 @@ Жодного результату Виберіть мережу Оберіть гаманець - 1 міс. - 1 рік - 24 год. - 3 міс. - 6 міс. + + + 24г + + - Увесь + Усе Досвідчені покупці За рейтингом Сортувати за @@ -394,7 +395,7 @@ Загальна кількість монет, які доступні для торгівлі та перебувають в обігу на ринку Досвідчені покупці Мережеві покупці з додатковою вимогою мати не менше 100 вихідних транзакцій - Повністю розведена ринкова капіталізація + Повн. розведена кап. Загальна теоретична вартість криптовалюти, якщо всі монети, які могли б існувати, перебувають в обігу, включаючи ті, що не перебувають в обігу в даний час Дата створення Високий @@ -661,6 +662,7 @@ Це призведе до видалення гаманця з застосунку. Сам гаманець можна додати знову. Ім\'я Сума для стейкінгу має бути не менше %s + Сума стейкінгу буде округлена до %1$s TRX відповідно до правил мережі. Зняти кошти Процентна ставка Річний відсоток, який ви можете отримати, беручи участь у стейкінгу. @@ -733,6 +735,7 @@ Транзакція обробляється! Наразі триває перевірка в блокчейні. Це може зайняти кілька хвилин. Розблокування Розблокувати + Розблокування Вивід зі стейкінгу Зняти зі стейкінгу Виведення зі стейкінгу %s @@ -875,6 +878,8 @@ Помилка активації За рішенням розробників мережі BNB стандарт BEP-2 перестане підтримуватись у червні 2024 року. Щоб не втратити свої активи, їх необхідно конвертувати у стандарт BEP-20. Використовуйте функцію обміну, щоб перевести їх у мережу BNB Smart Chain. Відключення мережі BNB Beacon Chain + Будь ласка, поповніть рахунок на %1$s для покриття комісії мережі + Недостатньо коштів для покриття комісії мережі Можна краще Вподобати Зрозуміло! diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index 12c3f39762..e58d6eaa30 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -567,7 +567,7 @@ Scan the card to change its settings. The changes will impact only the card you\'ve scanned and will not affect other cards tied to your wallet. Get your card ready! Already included in the entered address - The commission amount is %s times the recommended amount. Make sure that the custom settings are correct. + Your commission amount is %s times higher than the recommended amount. Please review and adjust your custom settings. You specified a commission below the recommended amount, which could cause a delay in your transaction. Continue? Reason: %1$s\nCode: %2$s The transaction is not completed @@ -602,7 +602,7 @@ Total exceeds balance A balance of at least %s is required to keep your account on the blockchain to prevent security risks. This amount will remain in your balance and cannot be withdrawn. Existential deposit - The commission amount is %s times the recommended amount. Make sure that the custom settings are correct. + Your commission amount is %s times higher than the recommended amount. Please review and adjust your custom settings. Custom fee is high Due to the peculiarities of the %1$s network, the fee for transferring the entire balance is higher. To reduce the commission, you can leave %2$s. The fee is higher @@ -648,6 +648,8 @@ The amount to stake must be at least %s Staking amount will be rounded to %1$s TRX due to network rules. Claim unstaked + Stake account fee + A staking account is a special account where staked SOL tokens are stored. It is created when you delegate your tokens to a validator to participate in transaction validation and earn rewards. A small fee is charged for creating the staking account, which is returned after the staking is completed. Annual percentage rate The annual percentage return you can earn from participating in staking. APR @@ -703,6 +705,7 @@ Block Day Each day + Each ~%1$ssec Epoch Era Hour @@ -719,6 +722,7 @@ The transaction is being processed! Validation is currently underway in the blockchain. This may take a few minutes. Unbonding Unlock + Unlocking Unstaked Unstaking Unstaking assets %s diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index c2a2c681a5..9ed92bf14b 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -19,6 +19,7 @@ import com.tangem.features.staking.impl.presentation.state.bottomsheet.InfoType import com.tangem.features.staking.impl.presentation.state.converters.RewardsValidatorStateConverter import com.tangem.features.staking.impl.presentation.state.converters.YieldBalancesConverter import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents +import com.tangem.lib.crypto.BlockchainUtils.isCosmos import com.tangem.lib.crypto.BlockchainUtils.isPolkadot import com.tangem.utils.Provider import com.tangem.utils.isNullOrZero @@ -201,12 +202,12 @@ internal class SetInitialDataStateTransformer( private fun createRewardScheduleItem( rewardSchedule: Yield.Metadata.RewardSchedule, ): RoundedListWithDividersItemData? { - val endTextId = rewardScheduleResources[rewardSchedule] ?: return null + val endTextReference = getRewardScheduleText(rewardSchedule) ?: return null return RoundedListWithDividersItemData( id = R.string.staking_details_reward_schedule, - startText = TextReference.Res(R.string.staking_details_reward_schedule), - endText = TextReference.Res(endTextId), + startText = resourceReference(R.string.staking_details_reward_schedule), + endText = endTextReference, iconClick = { clickIntents.onInfoClick(InfoType.REWARD_SCHEDULE) }, ) } @@ -252,21 +253,34 @@ internal class SetInitialDataStateTransformer( return resourceReference(R.string.common_range, wrappedList(formattedMinApr, formattedMaxApr)) } - companion object { - private val EQUALITY_THRESHOLD = BigDecimal(1E-10) + private fun getRewardScheduleText(rewardSchedule: Yield.Metadata.RewardSchedule): TextReference? { + return when (rewardSchedule) { + Yield.Metadata.RewardSchedule.BLOCK -> { + val networkId = cryptoCurrencyStatusProvider().currency.network.id.value + when { + isCosmos(networkId) -> resourceReference( + R.string.staking_reward_schedule_each_sec, + wrappedList(COSMOS_BLOCK_TIME), + ) + else -> resourceReference(R.string.staking_reward_schedule_each_day) + } + } + Yield.Metadata.RewardSchedule.WEEK -> resourceReference(R.string.staking_reward_schedule_week) + Yield.Metadata.RewardSchedule.HOUR -> resourceReference(R.string.staking_reward_schedule_hour) + Yield.Metadata.RewardSchedule.DAY -> resourceReference(R.string.staking_reward_schedule_each_day) + Yield.Metadata.RewardSchedule.MONTH -> resourceReference(R.string.staking_reward_schedule_month) + Yield.Metadata.RewardSchedule.ERA -> resourceReference(R.string.staking_reward_schedule_era) + Yield.Metadata.RewardSchedule.EPOCH -> resourceReference(R.string.staking_reward_schedule_epoch) + Yield.Metadata.RewardSchedule.UNKNOWN -> null + } + } - private val rewardScheduleResources = mapOf( - Yield.Metadata.RewardSchedule.BLOCK to R.string.staking_reward_schedule_each_day, - Yield.Metadata.RewardSchedule.WEEK to R.string.staking_reward_schedule_week, - Yield.Metadata.RewardSchedule.HOUR to R.string.staking_reward_schedule_hour, - Yield.Metadata.RewardSchedule.DAY to R.string.staking_reward_schedule_each_day, - Yield.Metadata.RewardSchedule.MONTH to R.string.staking_reward_schedule_month, - Yield.Metadata.RewardSchedule.ERA to R.string.staking_reward_schedule_era, - Yield.Metadata.RewardSchedule.EPOCH to R.string.staking_reward_schedule_epoch, - Yield.Metadata.RewardSchedule.UNKNOWN to null, - ) + private companion object { + val EQUALITY_THRESHOLD = BigDecimal(1E-10) - private val rewardClaimingResources = mapOf( + const val COSMOS_BLOCK_TIME = "20" // 20 seconds + + val rewardClaimingResources = mapOf( Yield.Metadata.RewardClaiming.MANUAL to R.string.staking_reward_claiming_manual, Yield.Metadata.RewardClaiming.AUTO to R.string.staking_reward_claiming_auto, Yield.Metadata.RewardSchedule.UNKNOWN to null, From 557aae44acc03675dfdf512d7196ee556324e178 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 14:45:37 +0500 Subject: [PATCH 09/25] Updated on 2026-08-14 --- .../tangem/core/ui/utils/DecimalFormatterExt.kt | 2 +- .../operations/TokenListSortingOperations.kt | 14 ++++++++++++-- .../factory/TokenDetailsLoadedBalanceConverter.kt | 5 +++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/core/ui/src/main/java/com/tangem/core/ui/utils/DecimalFormatterExt.kt b/core/ui/src/main/java/com/tangem/core/ui/utils/DecimalFormatterExt.kt index 2d685763e3..a251b0c9ed 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/utils/DecimalFormatterExt.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/utils/DecimalFormatterExt.kt @@ -138,7 +138,7 @@ fun String.parseToBigDecimal(decimals: Int): BigDecimal { } } -fun BigDecimal.parseBigDecimal(decimals: Int, roundingMode: RoundingMode = RoundingMode.DOWN): String { +fun BigDecimal.parseBigDecimal(decimals: Int, roundingMode: RoundingMode = RoundingMode.HALF_UP): String { val decimalFormat = DecimalFormat().apply { decimalFormatSymbols = DecimalFormatSymbols(Locale.getDefault()) isParseBigDecimal = true diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListSortingOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListSortingOperations.kt index 354252452c..7e4bc12ae2 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListSortingOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/TokenListSortingOperations.kt @@ -7,7 +7,9 @@ import arrow.core.raise.either import arrow.core.raise.ensure import arrow.core.raise.ensureNotNull import arrow.core.toNonEmptyListOrNull +import com.tangem.domain.staking.model.stakekit.YieldBalance import com.tangem.domain.tokens.model.* +import com.tangem.utils.extensions.orZero import java.math.BigDecimal internal class TokenListSortingOperations( @@ -83,7 +85,7 @@ internal class TokenListSortingOperations( return if (isAnyTokenLoading) { tokens } else { - tokens.sortedByDescending { it.value.fiatAmount ?: BigDecimal.ZERO } + tokens.sortedByDescending { it.getTotalBalance() } .toNonEmptyListOrNull() ?: error("Tokens can not be empty here") } @@ -92,12 +94,20 @@ internal class TokenListSortingOperations( private fun sortGroupsByBalance(groupsWithSortedTokens: NonEmptyList): NonEmptyList { return groupsWithSortedTokens .sortedByDescending { group -> - group.currencies.sumOf { it.value.fiatAmount ?: BigDecimal.ZERO } + group.currencies.sumOf { it.getTotalBalance() } } .toNonEmptyListOrNull() ?: error("Tokens can not be empty here") } + private fun CryptoCurrencyStatus.getTotalBalance(): BigDecimal { + val yieldBalance = value.yieldBalance as? YieldBalance.Data + val totalYieldBalance = yieldBalance?.getTotalWithRewardsStakingBalance().orZero() + val totalFiatYieldBalance = totalYieldBalance.multiply(value.fiatRate.orZero()) + + return value.fiatAmount?.plus(totalFiatYieldBalance).orZero() + } + sealed class Error { object EmptyTokens : Error() diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 2419e894d1..190a186493 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -153,8 +153,9 @@ internal class TokenDetailsLoadedBalanceConverter( StakingBlockUM.Error(iconState = iconState) } else -> { - val stakingRewardAmount = yieldBalance?.getRewardStakingBalance() - val stakingFiatAmount = stakingCryptoAmount?.let { status.value.fiatRate?.multiply(it) } + val fiatRate = status.value.fiatRate + val stakingRewardAmount = yieldBalance?.getRewardStakingBalance()?.let { fiatRate?.multiply(it) } + val stakingFiatAmount = stakingCryptoAmount?.let { fiatRate?.multiply(it) } getStakedState( status = status, From e3b0788de9ff3e4e8d81d6220e313157d04e0f28 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 16:16:19 +0300 Subject: [PATCH 10/25] Updated on 2026-08-14 --- .../markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt | 6 ++++++ .../ui/preview/PreviewAddToPortfolioBSContentProvider.kt | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt index b73ba99609..4f99ce0afd 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt @@ -19,6 +19,7 @@ import androidx.compose.ui.layout.onGloballyPositioned import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.util.fastForEachIndexed @@ -200,10 +201,13 @@ private fun NetworkSelection(state: SelectNetworkUM, modifier: Modifier = Modifi Text( modifier = Modifier .align(Alignment.CenterVertically) + .weight(1f, fill = false) .alignByBaseline(), text = state.tokenName, style = TangemTheme.typography.body1, color = TangemTheme.colors.text.primary1, + overflow = TextOverflow.Ellipsis, + maxLines = 1, ) SpacerW6() Text( @@ -213,6 +217,8 @@ private fun NetworkSelection(state: SelectNetworkUM, modifier: Modifier = Modifi text = state.tokenCurrencySymbol, style = TangemTheme.typography.body1, color = TangemTheme.colors.text.tertiary, + overflow = TextOverflow.Visible, + maxLines = 1, ) } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewAddToPortfolioBSContentProvider.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewAddToPortfolioBSContentProvider.kt index 3b0e811163..3c8cb60016 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewAddToPortfolioBSContentProvider.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/preview/PreviewAddToPortfolioBSContentProvider.kt @@ -62,14 +62,14 @@ internal class PreviewAddToPortfolioBSContentProvider : PreviewParameterProvider selectedWallet = userWallet, selectNetworkUM = SelectNetworkUM( tokenId = "etherium", - tokenName = "Etherium", + tokenName = "Etherium Etherium Etherium Etherium", tokenCurrencySymbol = "ETH", networks = persistentListOf( blockchainRow.copy( type = "MAIN", isMainNetwork = true, isSelected = true, - ), + ).copy(name = "Etherium Etherium Etherium Etherium"), *Array(25) { blockchainRow }, ), From 0ebe5e385f1b2d6d1f3aff59ad6f030218d1db10 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 16:08:49 +0300 Subject: [PATCH 11/25] Updated on 2026-08-14 --- core/res/src/main/res/values-ru/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index 6ffdadf52b..b64757fd46 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -356,6 +356,7 @@ Невозможно загрузить данные Нет данных Быстрые действия + Искать на маркете Результат Токены с капитализацией меньше 100к USD Показать токены diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index e58d6eaa30..b3ac1d05be 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -356,6 +356,7 @@ Unable to load the data… No data Quick actions + Search through the market Result See tokens under 100k USD market cap Show tokens From 0eab4907a27cbe10de2eb64ef6e7beaadcac25b9 Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 19:17:55 +0300 Subject: [PATCH 12/25] Updated on 2026-08-14 --- .../com/tangem/datasource/di/DevTangemApi.kt | 8 ---- .../com/tangem/datasource/di/NetworkModule.kt | 40 +++++-------------- .../data/markets/di/MarketsDataModule.kt | 5 +-- .../presentation/wallet/ui/WalletScreen.kt | 5 +-- 4 files changed, 15 insertions(+), 43 deletions(-) delete mode 100644 core/datasource/src/main/java/com/tangem/datasource/di/DevTangemApi.kt diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/DevTangemApi.kt b/core/datasource/src/main/java/com/tangem/datasource/di/DevTangemApi.kt deleted file mode 100644 index 4bfacf89db..0000000000 --- a/core/datasource/src/main/java/com/tangem/datasource/di/DevTangemApi.kt +++ /dev/null @@ -1,8 +0,0 @@ -package com.tangem.datasource.di - -import javax.inject.Qualifier - -@Qualifier -@MustBeDocumented -@Retention(AnnotationRetention.RUNTIME) -annotation class DevTangemApi \ No newline at end of file diff --git a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt index c692a451c2..667e63d05e 100644 --- a/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt +++ b/core/datasource/src/main/java/com/tangem/datasource/di/NetworkModule.kt @@ -35,7 +35,6 @@ import javax.inject.Singleton @InstallIn(SingletonComponent::class) internal object NetworkModule { - private const val DEV_V1_TANGEM_TECH_BASE_URL = "https://devapi.tangem-tech.com/v1/" private const val PROD_V2_TANGEM_TECH_BASE_URL = "https://api.tangem-tech.com/v2/" private const val TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS = 60L @@ -128,44 +127,27 @@ internal object NetworkModule { } @Provides - @DevTangemApi - @Singleton - fun provideTangemTechDevApi( - @NetworkMoshi moshi: Moshi, - @ApplicationContext context: Context, - appVersionProvider: AppVersionProvider, - ): TangemTechApi { - return provideTangemTechApiInternal( - moshi = moshi, - context = context, - appVersionProvider = appVersionProvider, - baseUrl = DEV_V1_TANGEM_TECH_BASE_URL, - ) - } - - // TODO: [REDACTED_JIRA] - @Provides - @DevTangemApi @Singleton fun provideTangemTechMarketsApi( @NetworkMoshi moshi: Moshi, @ApplicationContext context: Context, - appVersionProvider: AppVersionProvider, + apiConfigsManager: ApiConfigsManager, ): TangemTechMarketsApi { - return provideTangemTechApiInternal( + return createApi( + id = ApiConfig.ID.TangemTech, moshi = moshi, context = context, - appVersionProvider = appVersionProvider, - baseUrl = DEV_V1_TANGEM_TECH_BASE_URL, - timeouts = Timeouts( - callTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, - connectTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, - readTimeoutSeconds = TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, - ), - requestHeaders = listOf(AppVersionPlatformHeaders(appVersionProvider)), + apiConfigsManager = apiConfigsManager, + clientBuilder = { + this.callTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .connectTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .readTimeout(TANGEM_TECH_MARKETS_SERVICE_TIMEOUT_SECONDS, TimeUnit.SECONDS) + .applyTimeoutAnnotations() + }, ) } + @Deprecated("use createApi instead") private inline fun provideTangemTechApiInternal( moshi: Moshi, context: Context, diff --git a/data/markets/src/main/java/com/tangem/data/markets/di/MarketsDataModule.kt b/data/markets/src/main/java/com/tangem/data/markets/di/MarketsDataModule.kt index 4ef2f1e094..fa4e3d492f 100644 --- a/data/markets/src/main/java/com/tangem/data/markets/di/MarketsDataModule.kt +++ b/data/markets/src/main/java/com/tangem/data/markets/di/MarketsDataModule.kt @@ -4,7 +4,6 @@ import com.tangem.core.analytics.api.AnalyticsEventHandler import com.tangem.data.markets.DefaultMarketsTokenRepository import com.tangem.datasource.api.markets.TangemTechMarketsApi import com.tangem.datasource.api.tangemTech.TangemTechApi -import com.tangem.datasource.di.DevTangemApi import com.tangem.datasource.local.userwallet.UserWalletsStore import com.tangem.domain.markets.repositories.MarketsTokenRepository import com.tangem.utils.coroutines.CoroutineDispatcherProvider @@ -21,8 +20,8 @@ internal object MarketsDataModule { @Provides @Singleton fun provideMarketsRepository( - @DevTangemApi marketsApi: TangemTechMarketsApi, - @DevTangemApi tangemTechApi: TangemTechApi, + marketsApi: TangemTechMarketsApi, + tangemTechApi: TangemTechApi, userWalletsStore: UserWalletsStore, dispatchers: CoroutineDispatcherProvider, analyticsEventHandler: AnalyticsEventHandler, diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index 7243dbb143..a42d33d598 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -407,7 +407,6 @@ private inline fun BaseScaffoldWithMarkets( sheetContainerColor = backgroundColor.value, scaffoldState = scaffoldState, sheetPeekHeight = peekHeight, - sheetTonalElevation = 8.dp, sheetShadowElevation = 8.dp, sheetShape = TangemTheme.shapes.bottomSheetLarge, sheetContent = { @@ -645,7 +644,7 @@ private fun BottomSheetStateEffects( val systemUiController = rememberSystemUiController() val navigationBarColor = TangemTheme.colors.background.primary - LaunchedEffect(Unit) { + LaunchedEffect(navigationBarColor) { delay(timeMillis = 100) when (bottomSheetState.currentValue) { TangemSheetValue.Hidden, @@ -660,7 +659,7 @@ private fun BottomSheetStateEffects( } } - LaunchedEffect(key1 = bottomSheetState.targetValue, navigationBarColor) { + LaunchedEffect(bottomSheetState.targetValue, navigationBarColor) { when (bottomSheetState.targetValue) { TangemSheetValue.Hidden, TangemSheetValue.Expanded, From 5e72f138cef926a2a09a502b3055646d82f8cd1f Mon Sep 17 00:00:00 2001 From: Tangem Date: Tue, 17 Sep 2024 22:14:05 +0500 Subject: [PATCH 13/25] Updated on 2026-08-14 --- .../amplitude/AmplitudeAnalyticsHandler.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt index 5eed564c97..2aa36c5413 100644 --- a/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt +++ b/app/src/main/java/com/tangem/tap/common/analytics/handlers/amplitude/AmplitudeAnalyticsHandler.kt @@ -18,10 +18,14 @@ class AmplitudeAnalyticsHandler( } class Builder : AnalyticsHandlerBuilder { - override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler? = when { - !data.isDebug -> AmplitudeClient(data.application, data.config.amplitudeApiKey) - data.isDebug && data.logConfig.amplitude -> AmplitudeLogClient(data.jsonConverter) - else -> null - }?.let { AmplitudeAnalyticsHandler(it) } + override fun build(data: AnalyticsHandlerBuilder.Data): AnalyticsHandler { + return AmplitudeAnalyticsHandler( + client = if (data.logConfig.amplitude) { + AmplitudeLogClient(data.jsonConverter) + } else { + AmplitudeClient(data.application, data.config.amplitudeApiKey) + }, + ) + } } } \ No newline at end of file From e86615242b20702413120cf89117db6eb18abd50 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 11:39:10 +0500 Subject: [PATCH 14/25] Updated on 2026-08-14 --- .../components/inputrow/InputRowImageBase.kt | 6 +++-- .../components/inputrow/InputRowImageInfo.kt | 3 +++ .../inputrow/InputRowImageSelector.kt | 3 +++ .../inputrow/inner/InputRowAsyncImage.kt | 10 ++++++-- .../res/drawable/ic_staking_filled_18.xml | 9 +++++++ .../ui/StakingClaimRewardsValidatorContent.kt | 1 + .../ui/StakingInitialInfoContent.kt | 1 + .../ui/StakingValidatorListContent.kt | 6 ++--- .../ui/ValidatorImagePlaceholder.kt | 25 +++++++++++++++++++ .../presentation/ui/block/ValidatorBlock.kt | 2 ++ 10 files changed, 58 insertions(+), 8 deletions(-) create mode 100644 core/ui/src/main/res/drawable/ic_staking_filled_18.xml create mode 100644 features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/ValidatorImagePlaceholder.kt diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt index 0991dcdf5a..6db1972160 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageBase.kt @@ -39,6 +39,7 @@ import com.tangem.core.ui.res.TangemThemePreview * @param captionColor caption text color * @param isGrayscaleImage whether to display grayscale image * @param iconEndRes icon to end of row + * @param onImageError composable to show if image loading failed * @param extraContent extra content */ @Composable @@ -53,6 +54,7 @@ internal fun InputRowImageBase( iconTint: Color = TangemTheme.colors.icon.informative, isGrayscaleImage: Boolean = false, iconEndRes: Int? = null, + onImageError: (@Composable () -> Unit)? = null, extraContent: (@Composable RowScope.() -> Unit)? = null, ) { Row( @@ -63,13 +65,13 @@ internal fun InputRowImageBase( InputRowAsyncImage( imageUrl = imageUrl, isGrayscale = isGrayscaleImage, + onImageError = onImageError, modifier = Modifier .size(TangemTheme.dimens.spacing36) .clip(TangemTheme.shapes.roundedCornersXLarge), ) SpacerW12() - } - if (iconRes != null) { + } else if (iconRes != null) { Box( contentAlignment = Alignment.Center, modifier = Modifier diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageInfo.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageInfo.kt index 19bb005a00..2905e007b7 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageInfo.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageInfo.kt @@ -35,6 +35,7 @@ import com.tangem.core.ui.res.TangemThemePreview * @param captionColor caption text color * @param isGrayscaleImage whether to display grayscale image * @param iconEndRes icon to end of row + * @param onImageError composable to show if image loading failed */ @Suppress("LongParameterList") @Composable @@ -52,6 +53,7 @@ fun InputRowImageInfo( iconTint: Color = TangemTheme.colors.icon.informative, isGrayscaleImage: Boolean = false, @DrawableRes iconEndRes: Int? = null, + onImageError: (@Composable () -> Unit)? = null, ) { Column( verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing6), @@ -75,6 +77,7 @@ fun InputRowImageInfo( captionColor = captionColor, isGrayscaleImage = isGrayscaleImage, iconEndRes = iconEndRes, + onImageError = onImageError, ) { Column( verticalArrangement = Arrangement.spacedBy(TangemTheme.dimens.spacing2), diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt index 6fcc6ef997..287edc1197 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/InputRowImageSelector.kt @@ -41,6 +41,7 @@ import java.math.BigDecimal * @param captionColor caption text color * @param isSelected true if selected * @param selectorContent selector content + * @param onImageError composable to show if image loading failed */ @Composable fun InputRowImageSelector( @@ -52,6 +53,7 @@ fun InputRowImageSelector( subtitleColor: Color = TangemTheme.colors.text.primary1, captionColor: Color = TangemTheme.colors.text.tertiary, isSelected: Boolean = false, + onImageError: (@Composable () -> Unit)? = null, selectorContent: @Composable ((isSelected: Boolean, isEnabled: Boolean, onSelect: () -> Unit) -> Unit), ) { InputRowImageBase( @@ -60,6 +62,7 @@ fun InputRowImageSelector( imageUrl = imageUrl, subtitleColor = subtitleColor, captionColor = captionColor, + onImageError = onImageError, modifier = modifier .clickable( onClick = onSelect, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt index b85e91ba30..3b46eeffc5 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/inputrow/inner/InputRowAsyncImage.kt @@ -18,9 +18,15 @@ import com.tangem.core.ui.utils.getGreyScaleColorFilter * @param imageUrl url of the image * @param modifier modifier * @param isGrayscale whether to apply grayscale filter + * @param onImageError composable to show if image loading failed */ @Composable -internal fun InputRowAsyncImage(imageUrl: String, modifier: Modifier = Modifier, isGrayscale: Boolean = false) { +internal fun InputRowAsyncImage( + imageUrl: String, + modifier: Modifier = Modifier, + isGrayscale: Boolean = false, + onImageError: (@Composable () -> Unit)? = null, +) { val (alpha, colorFilter) = getGreyScaleColorFilter(isGrayscale = isGrayscale) SubcomposeAsyncImage( modifier = modifier, @@ -33,7 +39,7 @@ internal fun InputRowAsyncImage(imageUrl: String, modifier: Modifier = Modifier, .build(), loading = { LoadingIcon() }, error = { - Box( + onImageError?.invoke() ?: Box( modifier = Modifier .background( color = TangemTheme.colors.background.tertiary, diff --git a/core/ui/src/main/res/drawable/ic_staking_filled_18.xml b/core/ui/src/main/res/drawable/ic_staking_filled_18.xml new file mode 100644 index 0000000000..e6741b6156 --- /dev/null +++ b/core/ui/src/main/res/drawable/ic_staking_filled_18.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingClaimRewardsValidatorContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingClaimRewardsValidatorContent.kt index cbcb806d97..fecd9f9cb6 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingClaimRewardsValidatorContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingClaimRewardsValidatorContent.kt @@ -52,6 +52,7 @@ internal fun StakingClaimRewardsValidatorContent( infoTitle = item.fiatAmount, infoSubtitle = item.cryptoAmount, imageUrl = item.validator?.image.orEmpty(), + onImageError = { ValidatorImagePlaceholder() }, modifier = modifier .roundedShapeItemDecoration(index, state.rewards.lastIndex, false) .background(TangemTheme.colors.background.action) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt index 6fa945af4f..f593e3e13b 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt @@ -282,6 +282,7 @@ private fun ActiveStakingBlock( imageUrl = balance.getImage(), iconRes = icon, iconTint = iconTint, + onImageError = { ValidatorImagePlaceholder() }, modifier = modifier .background(TangemTheme.colors.background.action) .clickable( diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt index 9f8db40d8e..c86ebb7e95 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingValidatorListContent.kt @@ -3,10 +3,7 @@ package com.tangem.features.staking.impl.presentation.ui import android.content.res.Configuration import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.systemBars +import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.material3.Icon import androidx.compose.runtime.Composable @@ -95,6 +92,7 @@ internal fun StakingValidatorListContent( ) } }, + onImageError = { ValidatorImagePlaceholder() }, ) } } diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/ValidatorImagePlaceholder.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/ValidatorImagePlaceholder.kt new file mode 100644 index 0000000000..d935c0e9ff --- /dev/null +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/ValidatorImagePlaceholder.kt @@ -0,0 +1,25 @@ +package com.tangem.features.staking.impl.presentation.ui + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.res.vectorResource +import com.tangem.core.ui.res.TangemTheme +import com.tangem.features.staking.impl.R + +@Composable +internal fun ValidatorImagePlaceholder() { + Icon( + painter = rememberVectorPainter(ImageVector.vectorResource(R.drawable.ic_staking_filled_18)), + contentDescription = null, + tint = TangemTheme.colors.icon.inactive, + modifier = Modifier + .background(TangemTheme.colors.icon.primary1, CircleShape) + .padding(TangemTheme.dimens.size9), + ) +} \ No newline at end of file diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt index be7909007e..e895963463 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/block/ValidatorBlock.kt @@ -16,6 +16,7 @@ import com.tangem.core.ui.res.TangemTheme import com.tangem.core.ui.utils.BigDecimalFormatter import com.tangem.features.staking.impl.R import com.tangem.features.staking.impl.presentation.state.ValidatorState +import com.tangem.features.staking.impl.presentation.ui.ValidatorImagePlaceholder import com.tangem.utils.extensions.orZero @Composable @@ -45,6 +46,7 @@ internal fun ValidatorBlock(validatorState: ValidatorState, onClick: () -> Unit) ) }, imageUrl = validatorState.chosenValidator.image.orEmpty(), + onImageError = { ValidatorImagePlaceholder() }, ) } } From 32398842df4e44f12ce2068e9041610b1d361fa1 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 11:39:33 +0500 Subject: [PATCH 15/25] Updated on 2026-08-14 --- .../transformers/AddStakingNotificationsTransformer.kt | 8 ++++---- .../SetConfirmationStateLoadingTransformer.kt | 8 +++----- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt index f4f4da10b4..181d37a8a2 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/AddStakingNotificationsTransformer.kt @@ -73,6 +73,7 @@ internal class AddStakingNotificationsTransformer( isSubtractAvailable = isSubtractAvailable, reduceAmountBy = reduceAmountBy, ) + val minimumRequirement = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum.orZero() val sendingAmount = if (isEnterAction) { checkAndCalculateSubtractedAmount( isAmountSubtractAvailable = isSubtractAvailable, @@ -84,7 +85,7 @@ internal class AddStakingNotificationsTransformer( } else { // No amount is taken from account balance on exit or pending actions BigDecimal.ZERO - } + }.max(minimumRequirement) val notifications = buildList { // errors @@ -106,7 +107,7 @@ internal class AddStakingNotificationsTransformer( amountState = amountState, feeState = feeState, sendingAmount = sendingAmount, - isFeeCoverage = isFeeCoverage && isEnterAction, + isFeeCoverage = isFeeCoverage && isEnterAction && !sendingAmount.equals(minimumRequirement), ) addInfoNotifications(prevState) @@ -223,11 +224,10 @@ internal class AddStakingNotificationsTransformer( cryptoCurrencyStatus: CryptoCurrencyStatus, onClick: (CryptoCurrency) -> Unit, ) { - val minimumRequirement = yield.args.enter.args[Yield.Args.ArgType.AMOUNT]?.minimum val balance = cryptoCurrencyStatus.value.amount ?: BigDecimal.ZERO if (!isSubtractionAvailable) return - val showNotification = sendingAmount + feeAmount > balance - minimumRequirement.orZero() + val showNotification = sendingAmount + feeAmount > balance if (showNotification) { val notification = if (actionType == StakingActionCommonType.ENTER) { NotificationUM.Error.TotalExceedsBalance diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt index bd88fa6ffc..27d5d30086 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetConfirmationStateLoadingTransformer.kt @@ -35,7 +35,7 @@ internal class SetConfirmationStateLoadingTransformer( availableValidators = yield.validators, ), notifications = persistentListOf(), - footerText = getFooter(prevState), + footerText = getFooter(prevState, chosenValidator), transactionDoneState = TransactionDoneState.Empty, pendingAction = possibleConfirmationState?.pendingAction, pendingActions = possibleConfirmationState?.pendingActions, @@ -45,14 +45,12 @@ internal class SetConfirmationStateLoadingTransformer( ) } - private fun getFooter(state: StakingUiState): TextReference { + private fun getFooter(state: StakingUiState, validator: Yield.Validator): TextReference { val amountState = state.amountState as? AmountState.Data - val confirmationState = state.confirmationState as? StakingStates.ConfirmationState.Data - val validatorState = confirmationState?.validatorState as? ValidatorState.Content val isEnterAction = state.actionType == StakingActionCommonType.ENTER - val apr = validatorState?.chosenValidator?.apr.orZero() + val apr = validator.apr.orZero() val amountDecimal = amountState?.amountTextField?.fiatAmount?.value val potentialReward = amountDecimal?.multiply(apr) From f6950cee54bbb194afb0b53dbe0ccfbb0bf508af Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 12:19:42 +0200 Subject: [PATCH 16/25] Updated on 2026-08-14 --- core/res/src/main/res/values-ja/strings.xml | 3 +++ core/res/src/main/res/values-ru/strings.xml | 8 +++++--- core/res/src/main/res/values/strings.xml | 6 +++--- 3 files changed, 11 insertions(+), 6 deletions(-) diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index 1a848e9582..cc239e89d7 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -353,6 +353,7 @@ データを読み込めません… データなし クイックアクション + マーケットから探す 結果 時価総額10万ドル以下のトークンを見る トークンを表示 @@ -857,6 +858,8 @@ アクティベーションに失敗しました BNBネットワーク開発者によると、BEP-2規格のサポートは2024年6月に終了します。この規格の資産を失わないために、BEP-20規格に変換してください。BNBスマートチェーンネットワークへ移行するには、Tangemのスワップサービスをご利用ください。 BNBビーコンチェーンは閉鎖されます。 + ネットワーク手数料をカバーするために%1$sを入金してください + ネットワーク手数料をカバーする資金が不足しています もっと良くなるはず 気に入った はい、わかりました! diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index b64757fd46..f0811f5273 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -38,7 +38,7 @@ Слишком много попыток Вы отключили биометрическую аутентификацию на вашем телефоне и не сможете сохранять кошельки в приложении. Для сохранения кошельков, пожалуйста, включите функцию биометрической аутентификации в настройках телефона. Начать резервное копирование - С помощью банковской карты или банковского аккаунта + Используйте банковскую карту или другие методы оплаты %d карта %d карты @@ -276,7 +276,7 @@ Токены не найдены. Пожалуйста, попробуйте другой запрос ID: %s ID транзакции скопирован - С другой валютой в вашем кошельке + Конвертируйте одну из ваших валют в другую Информация ниже не является обязательной. Вы можете стереть её, если хотите. Расскажите, каких функций вам не хватает, и мы постараемся вам помочь. Скажите, пожалуйста, какая у вас карта? @@ -352,6 +352,7 @@ Мой портфель Рынок Чтобы создать адреса для выбранных сетей, отсканируйте вашу карту Tangem кошелька + Потяните вверх или коснитесь поисковой строки, чтобы добавить токен Данные раздела получены из следующих сетей: %s Невозможно загрузить данные Нет данных @@ -524,7 +525,7 @@ Доступ к камере запрещен %1$s (%2$s) в сети %3$s Отправляйте только %s на этот адрес. Использование другой сети может привести к утрате средств. - Покажи QR-код или поделись своим адресом + Переводите средства с другого кошелька или биржи Участвовать Не удалось загрузить информацию по реферальной программе. Пожалуйста, попробуйте позже. Не удалось загрузить информацию по реферальной программе. Код ошибки: %s. Пожалуйста, попробуйте позже. @@ -654,6 +655,7 @@ Это приведет к удалению кошелька из приложения. Сам кошелек можно добавить снова. Имя Сумма для стейкинга должна быть не менее %s + Согласно правилам сети, сумма стейкинга будет округлена до %1$sTRX. Забрать средства Стейкинг аккаунт — это специальный счет, на котором хранятся застейканные токены SOL. Он создается при делегировании ваших токенов валидатору для участия в подтверждении транзакций и получении наград. За создание стейкинг аккаунта взимается небольшая комиссия, которая возвращается после завершения стейкинга. Процентная ставка diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index b3ac1d05be..d1b74c37a7 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -39,7 +39,7 @@ Too many attempts You have disabled biometric authentication on your phone and will not be able to save wallets in the app. To save wallets, please enable the biometric authentication function in your phone settings. Start backup process - With your bank card or bank account + Use a bank card or other payment methods %d card %d cards @@ -275,7 +275,7 @@ No tokens found. Please try another request ID: %s Transaction ID copied - With another currency in your wallet + Convert one of your currencies to another The following information is optional. You can erase it if you don\'t want to share it. Tell us what functions you are missing, and we will try to help you. Please tell us what card do you have @@ -518,7 +518,7 @@ Camera access denied %1$s (%2$s) on %3$s network Send only %s to this address. Sending any other currency will result in its irreversible loss. - Show a QR-code or share your address + Transfer funds from another wallet or exchange Participate Failed to load the information about the referral program. Please try again later. Failed to load the information about the referral program. Error code: %s. Please try again later. From 8d6bb9a56b07ade093159b8e7d00c007e06a38d7 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 15:45:24 +0300 Subject: [PATCH 17/25] Updated on 2026-08-14 --- .../wallet/presentation/wallet/ui/WalletScreen.kt | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index a42d33d598..fad5dee568 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.geometry.* import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Path @@ -386,11 +387,13 @@ private inline fun BaseScaffoldWithMarkets( LocalMainBottomSheetColor provides remember { mutableStateOf(backgroundPrimary) }, ) { val backgroundColor = LocalMainBottomSheetColor.current + var isSearchFieldFocused by remember { mutableStateOf(false) } BottomSheetStateEffects( bottomSheetState = bottomSheetState, alertConfig = alertConfig, onBottomSheetStateChange = onBottomSheetStateChange, + isSearchFieldFocused = isSearchFieldFocused, ) TangemBottomSheetScaffold( @@ -422,7 +425,14 @@ private inline fun BaseScaffoldWithMarkets( modifier = Modifier.sizeIn(maxHeight = maxHeight - statusBarHeight), ) { Hand(Modifier.drawBehind { drawRect(backgroundColor.value) }) - bottomSheetContent() + Box( + modifier = Modifier + .onFocusChanged { + isSearchFieldFocused = it.isFocused + }, + ) { + bottomSheetContent() + } } }, content = { paddingValues -> @@ -640,6 +650,7 @@ private fun BottomSheetStateEffects( bottomSheetState: TangemSheetState, alertConfig: WalletAlertState?, onBottomSheetStateChange: (BottomSheetState) -> Unit, + isSearchFieldFocused: Boolean, ) { val systemUiController = rememberSystemUiController() val navigationBarColor = TangemTheme.colors.background.primary @@ -688,7 +699,7 @@ private fun BottomSheetStateEffects( val isKeyboardVisible by rememberIsKeyboardVisible() LaunchedEffect(isKeyboardVisible) { - if (isKeyboardVisible && alertConfig == null) { + if (isKeyboardVisible && alertConfig == null && isSearchFieldFocused) { bottomSheetState.expand() } } From 0358b2f858a05af1bcfb9ee960e4ee9a02566048 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 15:51:59 +0300 Subject: [PATCH 18/25] Updated on 2026-08-14 --- .../tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt index fad5dee568..d8b674e7df 100644 --- a/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt +++ b/features/wallet/impl/src/main/java/com/tangem/feature/wallet/presentation/wallet/ui/WalletScreen.kt @@ -473,6 +473,7 @@ private inline fun BaseScaffoldWithMarkets( state.showMarketsOnboarding, onDismissRequest = { coroutineScope.launch { bottomSheetState.partialExpand() } + state.onDismissMarketsOnboarding() }, ) From 0584147a364073b185ffa23ae104937e1f61aea2 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 17:48:37 +0300 Subject: [PATCH 19/25] Updated on 2026-08-14 --- gradle/dependencies.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index cb4e3722a1..7e7f4a8b81 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.15-778" +tangemBlockchainSdk = "release-app_5.15-780" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.15-382" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From 9754a874561610252267d6824940d8b371301c78 Mon Sep 17 00:00:00 2001 From: Tangem Date: Wed, 18 Sep 2024 20:07:33 +0500 Subject: [PATCH 20/25] Updated on 2026-08-14 --- core/res/src/main/res/values-de/strings.xml | 2 +- core/res/src/main/res/values-es/strings.xml | 1 + core/res/src/main/res/values-fr/strings.xml | 1 + core/res/src/main/res/values-ja/strings.xml | 2 +- core/res/src/main/res/values-ru/strings.xml | 3 ++- .../src/main/res/values-uk-rUA/strings.xml | 1 + core/res/src/main/res/values/strings.xml | 4 ++- .../SetInitialDataStateTransformer.kt | 7 +---- .../ui/StakingInitialInfoContent.kt | 3 --- .../TokenDetailsLoadedBalanceConverter.kt | 3 +-- .../factory/TokenStakingStateConverter.kt | 3 +-- .../state/utils/RewardScheduleUtils.kt | 26 ------------------- 12 files changed, 13 insertions(+), 43 deletions(-) delete mode 100644 features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/utils/RewardScheduleUtils.kt diff --git a/core/res/src/main/res/values-de/strings.xml b/core/res/src/main/res/values-de/strings.xml index c130e68816..a72160333d 100644 --- a/core/res/src/main/res/values-de/strings.xml +++ b/core/res/src/main/res/values-de/strings.xml @@ -383,6 +383,7 @@ Webseite Kaufdruck Die Differenz zwischen Käufer- und Verkäufervolumen + Kaufdruck Umlaufmenge Die Gesamtzahl der Coins, die für den Handel verfügbar sind und auf dem Markt zirkulieren Erfahrene Käufer @@ -707,7 +708,6 @@ Block Tag Täglich - Jeder %1$s Epoche Ära Stunde diff --git a/core/res/src/main/res/values-es/strings.xml b/core/res/src/main/res/values-es/strings.xml index 3c8fb3e199..0bfcf8de3d 100644 --- a/core/res/src/main/res/values-es/strings.xml +++ b/core/res/src/main/res/values-es/strings.xml @@ -382,6 +382,7 @@ Sitio web Presión de compra La diferencia entre el volumen de compradores y el volumen de vendedores + Presión de compra Suministro circulante El número total de monedas que están disponibles para el comercio y que circulan en el mercado. Compradores experimentados diff --git a/core/res/src/main/res/values-fr/strings.xml b/core/res/src/main/res/values-fr/strings.xml index d2745aa359..0d3cb6b2bc 100644 --- a/core/res/src/main/res/values-fr/strings.xml +++ b/core/res/src/main/res/values-fr/strings.xml @@ -382,6 +382,7 @@ Site web Pression d\'achat La différence entre le volume des acheteurs et le volume des vendeurs + Pression d\'achat Approvisionnement en circulation Le nombre total de pièces disponibles pour le trading et en circulation sur le marché Acheteurs expérimentés diff --git a/core/res/src/main/res/values-ja/strings.xml b/core/res/src/main/res/values-ja/strings.xml index cc239e89d7..cff94ccc70 100644 --- a/core/res/src/main/res/values-ja/strings.xml +++ b/core/res/src/main/res/values-ja/strings.xml @@ -380,6 +380,7 @@ ウェブサイト 買い圧力 買い手と売り手の取引量の差 + 買い圧力 循環供給量 取引可能で市場に流通しているコインの総数 経験豊富な買い手 @@ -698,7 +699,6 @@ ブロック 毎日 - %1$s毎 エポック 時代 diff --git a/core/res/src/main/res/values-ru/strings.xml b/core/res/src/main/res/values-ru/strings.xml index f0811f5273..fe50c2b14d 100644 --- a/core/res/src/main/res/values-ru/strings.xml +++ b/core/res/src/main/res/values-ru/strings.xml @@ -387,6 +387,7 @@ Веб-сайт Покуп. предпоч. Разница между объемом покупателей и продавцов + Покуп. предпоч. Циркулир. предл. Общее количество монет, доступных для торговли и находящихся в обращении на рынке Опытные трейдеры @@ -701,7 +702,7 @@ Блок День Каждый день - Каждые ~%1$s сек + Каждую минуту Эпоха Эра Час diff --git a/core/res/src/main/res/values-uk-rUA/strings.xml b/core/res/src/main/res/values-uk-rUA/strings.xml index 9e4b55bc64..c032f68459 100644 --- a/core/res/src/main/res/values-uk-rUA/strings.xml +++ b/core/res/src/main/res/values-uk-rUA/strings.xml @@ -391,6 +391,7 @@ Веб-сайт Давлення покупця Різниця між обсягом покупців та обсягом продавців + Давлення покупця Циркуляційний запас Загальна кількість монет, які доступні для торгівлі та перебувають в обігу на ринку Досвідчені покупці diff --git a/core/res/src/main/res/values/strings.xml b/core/res/src/main/res/values/strings.xml index d1b74c37a7..e95c0bc2b7 100644 --- a/core/res/src/main/res/values/strings.xml +++ b/core/res/src/main/res/values/strings.xml @@ -384,6 +384,7 @@ Website Buy pressure The difference between buyers volume and sellers volume + Buy pressure Circulating supply The total number of coins that are available for trading and are circulating in the market Experienced buyers @@ -678,6 +679,7 @@ Migrate Native staking Earned rewards will be sent to your wallet and available for use immediately + Stake securely and start earning your rewards Stake securely and start earning daily rewards Stake securely and start earning hourly rewards Stake securely and start earning monthly rewards @@ -706,7 +708,7 @@ Block Day Each day - Each ~%1$ssec + Each minute Epoch Era Hour diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt index 9ed92bf14b..517cbba094 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/transformers/SetInitialDataStateTransformer.kt @@ -258,10 +258,7 @@ internal class SetInitialDataStateTransformer( Yield.Metadata.RewardSchedule.BLOCK -> { val networkId = cryptoCurrencyStatusProvider().currency.network.id.value when { - isCosmos(networkId) -> resourceReference( - R.string.staking_reward_schedule_each_sec, - wrappedList(COSMOS_BLOCK_TIME), - ) + isCosmos(networkId) -> resourceReference(R.string.staking_reward_schedule_each_minute) else -> resourceReference(R.string.staking_reward_schedule_each_day) } } @@ -278,8 +275,6 @@ internal class SetInitialDataStateTransformer( private companion object { val EQUALITY_THRESHOLD = BigDecimal(1E-10) - const val COSMOS_BLOCK_TIME = "20" // 20 seconds - val rewardClaimingResources = mapOf( Yield.Metadata.RewardClaiming.MANUAL to R.string.staking_reward_claiming_manual, Yield.Metadata.RewardClaiming.AUTO to R.string.staking_reward_claiming_auto, diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt index f593e3e13b..679dd0675d 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/ui/StakingInitialInfoContent.kt @@ -57,7 +57,6 @@ import com.tangem.features.staking.impl.presentation.state.previewdata.InitialSt import com.tangem.features.staking.impl.presentation.state.stub.StakingClickIntentsStub import com.tangem.features.staking.impl.presentation.viewmodel.StakingClickIntents import com.tangem.utils.StringsSigns.DOT -import com.tangem.utils.StringsSigns.PLUS import com.tangem.utils.extensions.orZero private const val BANNER_BLOCK_KEY = "BannerBlock" @@ -231,8 +230,6 @@ private fun StakingRewardBlock( val (text, textColor) = when (rewardBlockType) { RewardBlockType.Rewards -> { annotatedReference { - append(PLUS) - appendSpace() append(rewardFiat.orMaskWithStars(isBalanceHidden)) appendSpace() append(DOT) diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt index 190a186493..dafdd53e8c 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenDetailsLoadedBalanceConverter.kt @@ -21,7 +21,6 @@ import com.tangem.feature.tokendetails.presentation.tokendetails.state.* import com.tangem.feature.tokendetails.presentation.tokendetails.state.components.TokenDetailsNotification import com.tangem.feature.tokendetails.presentation.tokendetails.state.factory.txhistory.TokenDetailsTxHistoryTransactionStateConverter import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getBalance -import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getStringResourceId import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.features.staking.api.featuretoggles.StakingFeatureToggles import com.tangem.features.tokendetails.impl.R @@ -204,7 +203,7 @@ internal class TokenDetailsLoadedBalanceConverter( formatArgs = wrappedList(apr), ), subtitleText = resourceReference( - id = stakingEntryInfo.rewardSchedule.getStringResourceId(), + id = R.string.staking_notification_earn_rewards_text, formatArgs = wrappedList(stakingEntryInfo.tokenSymbol), ), iconState = iconState, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt index b12e12eb53..14bd84bf23 100644 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt +++ b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/factory/TokenStakingStateConverter.kt @@ -8,7 +8,6 @@ import com.tangem.domain.staking.model.StakingEntryInfo import com.tangem.domain.staking.model.stakekit.StakingError import com.tangem.feature.tokendetails.presentation.tokendetails.state.StakingBlockUM import com.tangem.feature.tokendetails.presentation.tokendetails.state.TokenDetailsState -import com.tangem.feature.tokendetails.presentation.tokendetails.state.utils.getStringResourceId import com.tangem.feature.tokendetails.presentation.tokendetails.viewmodels.TokenDetailsClickIntents import com.tangem.features.tokendetails.impl.R import com.tangem.utils.Provider @@ -39,7 +38,7 @@ internal class TokenStakingStateConverter( formatArgs = wrappedList(apr), ), subtitleText = resourceReference( - id = stakingEntryInfo.rewardSchedule.getStringResourceId(), + id = R.string.staking_notification_earn_rewards_text, formatArgs = wrappedList(stakingEntryInfo.tokenSymbol), ), iconState = iconState, diff --git a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/utils/RewardScheduleUtils.kt b/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/utils/RewardScheduleUtils.kt deleted file mode 100644 index 1219166e7b..0000000000 --- a/features/tokendetails/impl/src/main/kotlin/com/tangem/feature/tokendetails/presentation/tokendetails/state/utils/RewardScheduleUtils.kt +++ /dev/null @@ -1,26 +0,0 @@ -package com.tangem.feature.tokendetails.presentation.tokendetails.state.utils - -import com.tangem.domain.staking.model.stakekit.Yield -import com.tangem.features.tokendetails.impl.R - -internal fun Yield.Metadata.RewardSchedule.getStringResourceId(): Int { - return when (this) { - Yield.Metadata.RewardSchedule.BLOCK, - Yield.Metadata.RewardSchedule.DAY, - Yield.Metadata.RewardSchedule.ERA, - Yield.Metadata.RewardSchedule.EPOCH, - -> R.string.staking_notification_earn_rewards_text_daily - - Yield.Metadata.RewardSchedule.HOUR, - -> R.string.staking_notification_earn_rewards_text_hourly - - Yield.Metadata.RewardSchedule.WEEK, - -> R.string.staking_notification_earn_rewards_text_weekly - - Yield.Metadata.RewardSchedule.MONTH, - -> R.string.staking_notification_earn_rewards_text_monthly - - else - -> R.string.staking_notification_earn_rewards_text_daily - } -} \ No newline at end of file From 2a46965f94a47109f9991c16f3038943c2448138 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 09:12:26 +0300 Subject: [PATCH 21/25] Updated on 2026-08-14 --- .../src/main/java/com/tangem/domain/common/TapWorkarounds.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt b/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt index 68b724e1b7..601ecc526b 100644 --- a/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt +++ b/domain/legacy/src/main/java/com/tangem/domain/common/TapWorkarounds.kt @@ -61,7 +61,7 @@ object TapWorkarounds { ) // TODO try remove if it's possible because we can configure on init sdk com.tangem.common.core.Config - private val excludedBatches = listOf("0027", "0030", "0031", "0035", "DA88") + private val excludedBatches = listOf("0027", "0030", "0031", "0035", "DA88", "AF56") private val excludedIssuers = listOf("TTM BANK") From ce97b0e6b7b0586382ebb554a406bc6e3a906641 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 09:02:35 +0300 Subject: [PATCH 22/25] Updated on 2026-08-14 --- .../domain/tokens/operations/CurrencyStatusOperations.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt index abdf3f94fd..c8990cebf4 100644 --- a/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt +++ b/domain/tokens/src/main/kotlin/com/tangem/domain/tokens/operations/CurrencyStatusOperations.kt @@ -61,7 +61,7 @@ internal class CurrencyStatusOperations( (yieldBalance as? YieldBalance.Data)?.address == status.address.defaultAddress.value val currentYieldBalance = yieldBalance.takeIf { isCurrentAddressStaking } return when { - ignoreQuote -> CryptoCurrencyStatus.NoQuote( + ignoreQuote || quote == null -> CryptoCurrencyStatus.NoQuote( amount = amount, hasCurrentNetworkTransactions = hasCurrentNetworkTransactions, pendingTransactions = currentTransactions, @@ -70,15 +70,14 @@ internal class CurrencyStatusOperations( ) currency is CryptoCurrency.Token && currency.isCustom -> CryptoCurrencyStatus.Custom( amount = amount, - fiatAmount = calculateFiatAmountOrNull(amount, quote?.fiatRate), - fiatRate = quote?.fiatRate, - priceChange = quote?.priceChange, + fiatAmount = calculateFiatAmountOrNull(amount, quote.fiatRate), + fiatRate = quote.fiatRate, + priceChange = quote.priceChange, hasCurrentNetworkTransactions = hasCurrentNetworkTransactions, pendingTransactions = currentTransactions, networkAddress = status.address, yieldBalance = currentYieldBalance, ) - quote == null -> CryptoCurrencyStatus.Loading else -> CryptoCurrencyStatus.Loaded( amount = amount, fiatAmount = calculateFiatAmount(amount, quote.fiatRate), From 7a2430c3d5230c3d2c9a5e1b20e742c4ed3e1e61 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 15:12:31 +0400 Subject: [PATCH 23/25] Updated on 2026-08-14 --- .../home/compose/views/StoriesButton.kt | 1 + .../com/tangem/core/ui/components/Buttons.kt | 9 ++++++- .../NotificationWithBackground.kt | 25 ++++++++++--------- .../notifications/OkxPromoNotification.kt | 15 +++++------ .../impl/ui/AddToPortfolioBottomSheet.kt | 1 + .../presentation/ui/SendNavigationButtons.kt | 3 ++- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesButton.kt b/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesButton.kt index 45b8745cca..c2e879dc2d 100644 --- a/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesButton.kt +++ b/app/src/main/java/com/tangem/tap/features/home/compose/views/StoriesButton.kt @@ -26,6 +26,7 @@ internal fun StoriesButton( showProgress = showProgress, enabled = true, shape = TangemTheme.shapes.roundedCornersXMedium, + textStyle = TangemTheme.typography.subtitle1, iconPadding = when (icon) { is TangemButtonIconPosition.Start -> TangemTheme.dimens.spacing4 is TangemButtonIconPosition.End, diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt index 9667a00860..e43a390155 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/Buttons.kt @@ -14,8 +14,8 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.tooling.preview.Preview import com.tangem.core.ui.R import com.tangem.core.ui.components.buttons.common.* -import com.tangem.core.ui.res.TangemThemePreview import com.tangem.core.ui.res.TangemTheme +import com.tangem.core.ui.res.TangemThemePreview // region TextButton /** @@ -102,6 +102,7 @@ fun PrimaryButton( enabled = enabled, showProgress = showProgress, size = size, + textStyle = TangemTheme.typography.subtitle1, ) } @@ -127,6 +128,7 @@ fun PrimaryButtonIconEnd( enabled = enabled, showProgress = showProgress, size = size, + textStyle = TangemTheme.typography.subtitle1, ) } @@ -153,6 +155,7 @@ fun PrimaryButtonIconEndTwoLines( showProgress = showProgress, additionalText = additionalText, size = TangemButtonSize.TwoLines, + textStyle = TangemTheme.typography.subtitle1, ) } @@ -176,6 +179,7 @@ fun PrimaryButtonIconStart( colors = TangemButtonsDefaults.primaryButtonColors, enabled = enabled, showProgress = showProgress, + textStyle = TangemTheme.typography.subtitle1, ) } // endregion PrimaryButton @@ -201,6 +205,7 @@ fun SecondaryButton( showProgress = showProgress, size = size, shape = shape, + textStyle = TangemTheme.typography.subtitle1, ) } @@ -224,6 +229,7 @@ fun SecondaryButtonIconEnd( colors = TangemButtonsDefaults.secondaryButtonColors, enabled = enabled, showProgress = showProgress, + textStyle = TangemTheme.typography.subtitle1, ) } @@ -247,6 +253,7 @@ fun SecondaryButtonIconStart( colors = TangemButtonsDefaults.secondaryButtonColors, enabled = enabled, showProgress = showProgress, + textStyle = TangemTheme.typography.subtitle1, ) } // endregion SecondaryButton diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt index a6031f054b..d76569543f 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/NotificationWithBackground.kt @@ -7,9 +7,9 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.defaultMinSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size -import androidx.compose.material3.ripple import androidx.compose.material3.Icon import androidx.compose.material3.Text +import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -132,17 +132,6 @@ fun NotificationWithBackground(config: NotificationConfig, modifier: Modifier = ) val isDarkMode = LocalIsInDarkTheme.current TangemButton( - text = button?.text?.resolveReference().orEmpty(), - icon = TangemButtonIconPosition.Start(button?.iconResId ?: R.drawable.ic_exchange_vertical_24), - onClick = button?.onClick ?: {}, - colors = TangemButtonColors( - backgroundColor = if (isDarkMode) Light4 else TangemTheme.colors.button.secondary, - contentColor = Dark6, - disabledBackgroundColor = TangemTheme.colors.button.disabled, - disabledContentColor = TangemTheme.colors.text.disabled, - ), - enabled = true, - showProgress = false, modifier = Modifier.constrainAs(buttonRef) { start.linkTo(parent.start, spacing12) end.linkTo(parent.end, spacing12) @@ -154,6 +143,18 @@ fun NotificationWithBackground(config: NotificationConfig, modifier: Modifier = Visibility.Visible } }, + text = button?.text?.resolveReference().orEmpty(), + icon = TangemButtonIconPosition.Start(button?.iconResId ?: R.drawable.ic_exchange_vertical_24), + onClick = button?.onClick ?: {}, + colors = TangemButtonColors( + backgroundColor = if (isDarkMode) Light4 else TangemTheme.colors.button.secondary, + contentColor = Dark6, + disabledBackgroundColor = TangemTheme.colors.button.disabled, + disabledContentColor = TangemTheme.colors.text.disabled, + ), + textStyle = TangemTheme.typography.subtitle1, + enabled = true, + showProgress = false, ) } } diff --git a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt index 2888045227..94f39ed5dd 100644 --- a/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt +++ b/core/ui/src/main/java/com/tangem/core/ui/components/notifications/OkxPromoNotification.kt @@ -110,6 +110,13 @@ private fun Button(config: NotificationConfig) { button?.let { val isDarkMode = LocalIsInDarkTheme.current TangemButton( + modifier = Modifier + .fillMaxWidth() + .padding( + start = TangemTheme.dimens.spacing12, + end = TangemTheme.dimens.spacing12, + bottom = TangemTheme.dimens.spacing12, + ), text = button.text.resolveReference(), icon = TangemButtonIconPosition.Start(button.iconResId ?: R.drawable.ic_exchange_vertical_24), onClick = button.onClick, @@ -119,15 +126,9 @@ private fun Button(config: NotificationConfig) { disabledBackgroundColor = TangemTheme.colors.button.disabled, disabledContentColor = TangemTheme.colors.text.disabled, ), + textStyle = TangemTheme.typography.subtitle1, enabled = true, showProgress = false, - modifier = Modifier - .fillMaxWidth() - .padding( - start = TangemTheme.dimens.spacing12, - end = TangemTheme.dimens.spacing12, - bottom = TangemTheme.dimens.spacing12, - ), ) } } diff --git a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt index 4f99ce0afd..73f6dca547 100644 --- a/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt +++ b/features/markets/impl/src/main/kotlin/com/tangem/features/markets/portfolio/impl/ui/AddToPortfolioBottomSheet.kt @@ -163,6 +163,7 @@ private fun ContinueButton( showProgress = false, size = TangemButtonSize.Default, colors = TangemButtonsDefaults.primaryButtonColors, + textStyle = TangemTheme.typography.subtitle1, onClick = onClick, animateContentChange = true, ) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt index 8cd6867e1d..85b4d38175 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt @@ -127,6 +127,7 @@ private fun SendNavigationButton( } } TangemButton( + modifier = Modifier.fillMaxWidth(), text = stringResource(buttonTextId), icon = buttonIcon, enabled = isButtonEnabled, @@ -135,8 +136,8 @@ private fun SendNavigationButton( buttonClick() }, showProgress = false, - modifier = Modifier.fillMaxWidth(), colors = TangemButtonsDefaults.primaryButtonColors, + textStyle = TangemTheme.typography.subtitle1, ) } } From 8a7dd57c13bb8ee5d5a550183e68ca155287468d Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 15:24:20 +0500 Subject: [PATCH 24/25] Updated on 2026-08-14 --- .../impl/presentation/state/utils/FeeCalculation.kt | 7 ++++++- gradle/dependencies.toml | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/FeeCalculation.kt b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/FeeCalculation.kt index 0f1857c60b..f3a7078d7d 100644 --- a/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/FeeCalculation.kt +++ b/features/staking/impl/src/main/java/com/tangem/features/staking/impl/presentation/state/utils/FeeCalculation.kt @@ -31,7 +31,12 @@ internal fun checkAndCalculateSubtractedAmount( reduceAmountBy = reduceAmountBy, ) return if (isFeeCoverage) { - balance.minus(reduceAmountBy).minus(feeValueRounded) + val reducedAmount = balance.minus(reduceAmountBy).minus(feeValueRounded) + if (isTron(cryptoCurrencyStatus.currency.network.id.value)) { + reducedAmount.setScale(0, RoundingMode.DOWN) + } else { + reducedAmount + } } else { amountValue } diff --git a/gradle/dependencies.toml b/gradle/dependencies.toml index 7e7f4a8b81..49b3c92007 100644 --- a/gradle/dependencies.toml +++ b/gradle/dependencies.toml @@ -89,7 +89,7 @@ markdownComposeView = "0.5.4" # endregion Other libraries # region Tangem -tangemBlockchainSdk = "release-app_5.15-780" +tangemBlockchainSdk = "release-app_5.15-781" #tangemBlockchainSdk = "0.0.1" # Keep it! - used for local builds tangemCardSdk = "release-app_5.15-382" #tangemCardSdk = "0.0.1" # Keep it! - used for local builds ^ From f181b8707ebe50fe7a4cb6f65d815327a72eaab6 Mon Sep 17 00:00:00 2001 From: Tangem Date: Thu, 19 Sep 2024 17:06:45 +0300 Subject: [PATCH 25/25] Updated on 2026-08-14 --- .../features/send/impl/presentation/ui/SendNavigationButtons.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt index 85b4d38175..864a75afa0 100644 --- a/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt +++ b/features/send/impl/src/main/java/com/tangem/features/send/impl/presentation/ui/SendNavigationButtons.kt @@ -275,7 +275,7 @@ private fun isButtonEnabled(currentState: SendUiCurrentScreen, uiState: SendUiSt private fun getTokenFeeSendingText(feeState: SendStates.FeeState, fee: Fee.Tron, sendingValue: String): TextReference { val suffix = when { - fee.feeEnergy == 0L -> { + fee.remainingEnergy == 0L -> { resourceReference( R.string.send_summary_transaction_description_suffix_including, wrappedList(feeState.getFiatValue()),