Updated on 2026-08-14

This commit is contained in:
Tangem 2025-04-01 16:21:50 +05:00
parent 6ddf9a25ae
commit e8f2ed8517
22 changed files with 463 additions and 81 deletions

View file

@ -1,10 +1,9 @@
package com.tangem.tap.di.domain
import com.tangem.domain.nft.FetchNFTCollectionAssetsUseCase
import com.tangem.domain.nft.FetchNFTCollectionsUseCase
import com.tangem.domain.nft.GetNFTCollectionsUseCase
import com.tangem.domain.nft.*
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
@ -20,30 +19,43 @@ internal object NFTDomainModule {
fun providesGetNFTCollectionsUseCase(
currenciesRepository: CurrenciesRepository,
nftRepository: NFTRepository,
): GetNFTCollectionsUseCase {
return GetNFTCollectionsUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
)
}
): GetNFTCollectionsUseCase = GetNFTCollectionsUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
)
@Provides
@Singleton
fun providesFetchNFTCollectionsUseCase(
currenciesRepository: CurrenciesRepository,
nftRepository: NFTRepository,
): FetchNFTCollectionsUseCase {
return FetchNFTCollectionsUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
)
}
): FetchNFTCollectionsUseCase = FetchNFTCollectionsUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
)
@Provides
@Singleton
fun providesFetchNFTCollectionAssetsUseCase(nftRepository: NFTRepository): FetchNFTCollectionAssetsUseCase {
return FetchNFTCollectionAssetsUseCase(
fun providesFetchNFTCollectionAssetsUseCase(nftRepository: NFTRepository): FetchNFTCollectionAssetsUseCase =
FetchNFTCollectionAssetsUseCase(
nftRepository = nftRepository,
)
}
@Provides
@Singleton
fun providesGetNFTAvailableNetworksUseCase(
nftRepository: NFTRepository,
currenciesRepository: CurrenciesRepository,
): GetNFTAvailableNetworksUseCase = GetNFTAvailableNetworksUseCase(
currenciesRepository = currenciesRepository,
nftRepository = nftRepository,
)
@Provides
@Singleton
fun providesFilterNFTAvailableNetworksUseCase(
dispatchers: CoroutineDispatcherProvider,
): FilterNFTAvailableNetworksUseCase = FilterNFTAvailableNetworksUseCase(
dispatchers = dispatchers,
)
}

View file

@ -13,6 +13,7 @@ import com.tangem.features.managetokens.component.ManageTokensComponent
import com.tangem.features.managetokens.component.ManageTokensSource
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
import com.tangem.features.nft.component.NFTCollectionsComponent
import com.tangem.features.nft.component.NFTReceiveComponent
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
import com.tangem.features.onramp.component.*
import com.tangem.features.pushnotifications.api.PushNotificationsComponent
@ -82,6 +83,7 @@ internal class ChildFactory @Inject constructor(
private val sendFeatureToggles: SendFeatureToggles,
private val redesignedWalletConnectComponentFactory: RedisegnedWalletConnectComponent.Factory,
private val nftCollectionsComponentFactory: NFTCollectionsComponent.Factory,
private val nftReceiveComponentFactory: NFTReceiveComponent.Factory,
private val testerRouter: TesterRouter,
private val routingFeatureToggles: RoutingFeatureToggles,
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
@ -405,6 +407,12 @@ internal class ChildFactory @Inject constructor(
params = NFTCollectionsComponent.Params(userWalletId = route.userWalletId),
componentFactory = nftCollectionsComponentFactory,
)
is AppRoute.NFTReceive ->
createComponentChild(
context = context,
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
componentFactory = nftReceiveComponentFactory,
)
is AppRoute.OnboardingNote,
is AppRoute.SaveWallet,
is AppRoute.OnboardingOther,
@ -743,6 +751,12 @@ internal class ChildFactory @Inject constructor(
params = NFTCollectionsComponent.Params(userWalletId = route.userWalletId),
componentFactory = nftCollectionsComponentFactory,
)
is AppRoute.NFTReceive ->
route.asComponentChild(
contextProvider = contextProvider(route, contextFactory),
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
componentFactory = nftReceiveComponentFactory,
)
}
// endregion
}

View file

@ -282,4 +282,9 @@ sealed class AppRoute(val path: String) : Route {
data class NFTCollections(
val userWalletId: UserWalletId,
) : AppRoute(path = "/nft_collections/${userWalletId.stringValue}")
@Serializable
data class NFTReceive(
val userWalletId: UserWalletId,
) : AppRoute(path = "/nft_receive/${userWalletId.stringValue}")
}

View file

@ -510,6 +510,9 @@
<string name="nft_collections_title">NFT collections</string>
<string name="nft_collections_warning_subtitle">Some data may not load</string>
<string name="nft_collections_warning_title">Temporary loading problems</string>
<string name="nft_empty_search">No results. Please try another request.</string>
<string name="nft_receive_title">Receive NFT</string>
<string name="nft_receive_subtitle">To My wallet</string>
<string name="nft_wallet_count">%1$d NFTs in %2$d collection</string>
<string name="nft_wallet_receive_nft">Tap here to receive first NFT</string>
<string name="nft_wallet_title">NFT collections</string>

View file

@ -153,6 +153,8 @@ internal class DefaultNFTRepository @Inject constructor(
}.saveIn(getCollectionJobHolder(collectionId)).join()
}
override suspend fun isNFTSupported(network: Network): Boolean = network.canHandleNFTs()
private suspend fun refreshSalePrice(
userWalletId: UserWalletId,
network: Network,

View file

@ -13,6 +13,8 @@ dependencies {
implementation(deps.arrow.core)
implementation(deps.kotlin.coroutines)
implementation(projects.core.utils)
implementation(projects.domain.core)
implementation(projects.domain.models)
implementation(projects.domain.nft.models)

View file

@ -0,0 +1,17 @@
package com.tangem.domain.nft
import com.tangem.domain.tokens.model.Network
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.coroutines.withContext
class FilterNFTAvailableNetworksUseCase(
private val dispatchers: CoroutineDispatcherProvider,
) {
suspend operator fun invoke(networks: List<Network>, searchQuery: String): List<Network> =
withContext(dispatchers.default) {
networks.filter {
it.name.contains(searchQuery, ignoreCase = true) ||
it.currencySymbol.contains(searchQuery, ignoreCase = true)
}
}
}

View file

@ -0,0 +1,22 @@
package com.tangem.domain.nft
import com.tangem.domain.nft.repository.NFTRepository
import com.tangem.domain.tokens.model.Network
import com.tangem.domain.tokens.repository.CurrenciesRepository
import com.tangem.domain.wallets.models.UserWalletId
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
class GetNFTAvailableNetworksUseCase(
private val currenciesRepository: CurrenciesRepository,
private val nftRepository: NFTRepository,
) {
operator fun invoke(userWalletId: UserWalletId): Flow<List<Network>> = currenciesRepository
.getWalletCurrenciesUpdates(userWalletId)
.map { cryptoCurrencies ->
cryptoCurrencies
.map { cryptoCurrency -> cryptoCurrency.network }
.distinct()
.filter { nftRepository.isNFTSupported(it) }
}
}

View file

@ -12,4 +12,6 @@ interface NFTRepository {
suspend fun refreshCollections(userWalletId: UserWalletId, networks: List<Network>)
suspend fun refreshAssets(userWalletId: UserWalletId, network: Network, collectionId: NFTCollection.Identifier)
suspend fun isNFTSupported(network: Network): Boolean
}

View file

@ -0,0 +1,14 @@
package com.tangem.features.nft.component
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.wallets.models.UserWalletId
interface NFTReceiveComponent : ComposableContentComponent {
data class Params(
val userWalletId: UserWalletId,
)
interface Factory : ComponentFactory<Params, NFTReceiveComponent>
}

View file

@ -5,6 +5,9 @@ import com.tangem.core.decompose.model.Model
import com.tangem.features.nft.collections.DefaultNFTCollectionsComponent
import com.tangem.features.nft.collections.model.NFTCollectionsModel
import com.tangem.features.nft.component.NFTCollectionsComponent
import com.tangem.features.nft.component.NFTReceiveComponent
import com.tangem.features.nft.receive.DefaultNFTReceiveComponent
import com.tangem.features.nft.receive.model.NFTReceiveModel
import dagger.Binds
import dagger.Module
import dagger.Provides
@ -30,10 +33,21 @@ internal object NFTFeatureModule {
internal interface NFTFeatureModuleBinds {
@Binds
@Singleton
fun bindComponentFactory(impl: DefaultNFTCollectionsComponent.Factory): NFTCollectionsComponent.Factory
fun bindNFTCollectionsComponentFactory(
impl: DefaultNFTCollectionsComponent.Factory,
): NFTCollectionsComponent.Factory
@Binds
@IntoMap
@ClassKey(NFTCollectionsModel::class)
fun bindModel(model: NFTCollectionsModel): Model
fun bindNFTCollectionsModel(model: NFTCollectionsModel): Model
@Binds
@Singleton
fun bindNFTReceiveComponentFactory(impl: DefaultNFTReceiveComponent.Factory): NFTReceiveComponent.Factory
@Binds
@IntoMap
@ClassKey(NFTReceiveModel::class)
fun bindNFTReceiveModel(model: NFTReceiveModel): Model
}

View file

@ -1,5 +1,6 @@
package com.tangem.features.nft.collections.model
import com.tangem.common.routing.AppRoute
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
@ -11,7 +12,8 @@ import com.tangem.domain.nft.FetchNFTCollectionAssetsUseCase
import com.tangem.domain.nft.GetNFTCollectionsUseCase
import com.tangem.domain.nft.models.NFTAsset
import com.tangem.domain.nft.models.NFTCollection
import com.tangem.features.nft.collections.entity.*
import com.tangem.features.nft.collections.entity.NFTCollectionsStateUM
import com.tangem.features.nft.collections.entity.NFTCollectionsUM
import com.tangem.features.nft.collections.entity.transformer.ChangeCollectionExpandedStateTransformer
import com.tangem.features.nft.collections.entity.transformer.ToggleSearchBarTransformer
import com.tangem.features.nft.collections.entity.transformer.UpdateDataStateTransformer
@ -119,7 +121,11 @@ internal class NFTCollectionsModel @Inject constructor(
}
private fun onReceiveClick() {
// TODO move to receive
router.push(
AppRoute.NFTReceive(
userWalletId = params.userWalletId,
),
)
}
private fun navigateBack() {

View file

@ -0,0 +1,37 @@
package com.tangem.features.nft.receive
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.core.decompose.model.getOrCreateModel
import com.tangem.features.nft.component.NFTReceiveComponent
import com.tangem.features.nft.receive.model.NFTReceiveModel
import com.tangem.features.nft.receive.ui.NFTReceive
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
internal class DefaultNFTReceiveComponent @AssistedInject constructor(
@Assisted context: AppComponentContext,
@Assisted private val params: NFTReceiveComponent.Params,
) : NFTReceiveComponent, AppComponentContext by context {
private val model: NFTReceiveModel = getOrCreateModel(params)
@Composable
override fun Content(modifier: Modifier) {
val state by model.state.collectAsStateWithLifecycle()
NFTReceive(state, modifier)
}
@AssistedFactory
interface Factory : NFTReceiveComponent.Factory {
override fun create(
context: AppComponentContext,
params: NFTReceiveComponent.Params,
): DefaultNFTReceiveComponent
}
}

View file

@ -1,9 +0,0 @@
package com.tangem.features.nft.receive.entity
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import kotlinx.collections.immutable.ImmutableList
internal data class NFTReceiveNetworksUM(
val searchBar: SearchBarUM,
val networks: ImmutableList<NFTNetworkUM>,
)

View file

@ -0,0 +1,23 @@
package com.tangem.features.nft.receive.entity
import androidx.compose.runtime.Immutable
import com.tangem.core.ui.components.bottomsheets.TangemBottomSheetConfig
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import kotlinx.collections.immutable.ImmutableList
internal data class NFTReceiveUM(
val onBackClick: () -> Unit,
val search: SearchBarUM,
val networks: Networks,
val bottomSheetConfig: TangemBottomSheetConfig?,
) {
@Immutable
sealed class Networks {
data object Empty : Networks()
data class Content(
val items: ImmutableList<NFTNetworkUM>,
) : Networks()
}
}

View file

@ -0,0 +1,13 @@
package com.tangem.features.nft.receive.entity.transformer
import com.tangem.features.nft.receive.entity.NFTReceiveUM
import com.tangem.utils.transformer.Transformer
internal class ToggleSearchBarTransformer(private val isActive: Boolean) : Transformer<NFTReceiveUM> {
override fun transform(prevState: NFTReceiveUM): NFTReceiveUM = prevState.copy(
search = prevState.search.copy(
isActive = isActive,
),
)
}

View file

@ -0,0 +1,34 @@
package com.tangem.features.nft.receive.entity.transformer
import com.tangem.core.ui.extensions.getActiveIconRes
import com.tangem.domain.tokens.model.Network
import com.tangem.features.nft.receive.entity.NFTNetworkUM
import com.tangem.features.nft.receive.entity.NFTReceiveUM
import com.tangem.utils.transformer.Transformer
import kotlinx.collections.immutable.toPersistentList
internal class UpdateDataStateTransformer(
private val networks: List<Network>,
private val onNetworkClick: (Network) -> Unit,
) : Transformer<NFTReceiveUM> {
override fun transform(prevState: NFTReceiveUM): NFTReceiveUM = prevState.copy(
networks = when {
networks.isEmpty() -> NFTReceiveUM.Networks.Empty
else -> NFTReceiveUM.Networks.Content(
items = networks
.map { it.transform() }
.toPersistentList(),
)
},
)
private fun Network.transform(): NFTNetworkUM = NFTNetworkUM(
id = id.value,
iconRes = getActiveIconRes(id.value),
name = name,
onItemClick = {
onNetworkClick(this)
},
)
}

View file

@ -0,0 +1,13 @@
package com.tangem.features.nft.receive.entity.transformer
import com.tangem.features.nft.receive.entity.NFTReceiveUM
import com.tangem.utils.transformer.Transformer
internal class UpdateSearchQueryTransformer(private val newQuery: String) : Transformer<NFTReceiveUM> {
override fun transform(prevState: NFTReceiveUM): NFTReceiveUM = prevState.copy(
search = prevState.search.copy(
query = newQuery,
),
)
}

View file

@ -0,0 +1,100 @@
package com.tangem.features.nft.receive.model
import com.tangem.core.decompose.di.ModelScoped
import com.tangem.core.decompose.model.Model
import com.tangem.core.decompose.model.ParamsContainer
import com.tangem.core.decompose.navigation.Router
import com.tangem.core.ui.components.fields.InputManager
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.domain.nft.FilterNFTAvailableNetworksUseCase
import com.tangem.domain.nft.GetNFTAvailableNetworksUseCase
import com.tangem.domain.tokens.model.Network
import com.tangem.features.nft.component.NFTReceiveComponent
import com.tangem.features.nft.impl.R
import com.tangem.features.nft.receive.entity.NFTReceiveUM
import com.tangem.features.nft.receive.entity.transformer.ToggleSearchBarTransformer
import com.tangem.features.nft.receive.entity.transformer.UpdateDataStateTransformer
import com.tangem.features.nft.receive.entity.transformer.UpdateSearchQueryTransformer
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import javax.inject.Inject
@ModelScoped
internal class NFTReceiveModel @Inject constructor(
override val dispatchers: CoroutineDispatcherProvider,
private val router: Router,
private val searchManager: InputManager,
private val getNFTAvailableNetworksUseCase: GetNFTAvailableNetworksUseCase,
private val filterNFTAvailableNetworksUseCase: FilterNFTAvailableNetworksUseCase,
paramsContainer: ParamsContainer,
) : Model() {
val state: StateFlow<NFTReceiveUM> get() = _state
private val _state = MutableStateFlow(
value = NFTReceiveUM(
onBackClick = ::navigateBack,
search = getInitialSearchBar(),
networks = NFTReceiveUM.Networks.Content(persistentListOf()),
bottomSheetConfig = null,
),
)
private val params: NFTReceiveComponent.Params = paramsContainer.require()
init {
subscribeToNFTAvailableNetworks()
}
private fun subscribeToNFTAvailableNetworks() {
combine(
flow = getNFTAvailableNetworksUseCase(params.userWalletId),
flow2 = searchManager.query.distinctUntilChanged(),
) { networks, query ->
filterNFTAvailableNetworksUseCase(networks, query)
}
.onEach { filteredNetworks ->
_state.update {
UpdateDataStateTransformer(
networks = filteredNetworks,
onNetworkClick = ::onNetworkClick,
).transform(it)
}
}
.launchIn(modelScope)
}
private fun onSearchQueryChange(newQuery: String) {
modelScope.launch {
_state.update { UpdateSearchQueryTransformer(newQuery).transform(it) }
searchManager.update(newQuery)
}
}
private fun getInitialSearchBar(): SearchBarUM = SearchBarUM(
placeholderText = resourceReference(R.string.common_search),
query = "",
isActive = false,
onQueryChange = ::onSearchQueryChange,
onActiveChange = ::toggleSearchBar,
)
private fun toggleSearchBar(isActive: Boolean) {
_state.update {
ToggleSearchBarTransformer(isActive).transform(it)
}
}
@Suppress("UnusedPrivateMember")
private fun onNetworkClick(network: Network) {
// TODO show receive bottom sheet
}
private fun navigateBack() {
router.pop()
}
}

View file

@ -0,0 +1,66 @@
package com.tangem.features.nft.receive.ui
import androidx.activity.compose.BackHandler
import androidx.compose.animation.AnimatedContent
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.ui.components.appbar.TangemTopAppBar
import com.tangem.core.ui.components.appbar.models.TopAppBarButtonUM
import com.tangem.core.ui.components.fields.SearchBar
import com.tangem.core.ui.components.fields.TangemSearchBarDefaults
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.nft.impl.R
import com.tangem.features.nft.receive.entity.NFTReceiveUM
@Composable
internal fun NFTReceive(state: NFTReceiveUM, modifier: Modifier = Modifier) {
BackHandler(onBack = state.onBackClick)
Scaffold(
modifier = modifier,
containerColor = TangemTheme.colors.background.secondary,
topBar = {
TangemTopAppBar(
modifier = Modifier.statusBarsPadding(),
startButton = TopAppBarButtonUM(
iconRes = R.drawable.ic_close_24,
onIconClicked = state.onBackClick,
),
title = stringResourceSafe(id = R.string.nft_receive_title),
subtitle = stringResourceSafe(id = R.string.nft_receive_subtitle),
)
},
content = { innerPadding ->
Column(
modifier = Modifier
.padding(innerPadding)
.fillMaxSize(),
) {
SearchBar(
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = TangemTheme.dimens.spacing16),
state = state.search,
colors = TangemSearchBarDefaults.secondaryTextFieldColors,
)
val contentModifier = Modifier
.padding(TangemTheme.dimens.spacing16)
AnimatedContent(
targetState = state.networks,
contentKey = { it::class },
label = "NFT Receive",
) {
when (val networks = it) {
is NFTReceiveUM.Networks.Content -> NFTReceiveNetworksContent(networks, contentModifier)
is NFTReceiveUM.Networks.Empty -> NFTReceiveNetworksEmpty(contentModifier)
}
}
}
},
)
}

View file

@ -1,9 +1,8 @@
package com.tangem.features.nft.receive.ui
import android.content.res.Configuration
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
@ -14,57 +13,39 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.tooling.preview.Preview
import com.tangem.core.ui.components.fields.SearchBar
import com.tangem.core.ui.components.fields.entity.SearchBarUM
import com.tangem.core.ui.extensions.resourceReference
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.core.ui.res.TangemThemePreview
import com.tangem.features.nft.impl.R
import com.tangem.features.nft.receive.entity.NFTNetworkUM
import com.tangem.features.nft.receive.entity.NFTReceiveNetworksUM
import com.tangem.features.nft.receive.entity.NFTReceiveUM
import kotlinx.collections.immutable.persistentListOf
@Composable
internal fun NFTReceiveNetworks(state: NFTReceiveNetworksUM, modifier: Modifier = Modifier) {
internal fun NFTReceiveNetworksContent(state: NFTReceiveUM.Networks.Content, modifier: Modifier = Modifier) {
val listState = rememberLazyListState()
Column(
LazyColumn(
modifier = modifier
.fillMaxSize()
.background(TangemTheme.colors.background.secondary)
.padding(
start = TangemTheme.dimens.spacing16,
end = TangemTheme.dimens.spacing16,
bottom = TangemTheme.dimens.spacing16,
),
.fillMaxWidth()
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary)
.animateContentSize(),
state = listState,
) {
SearchBar(
state = state.searchBar,
// TODO fix colors after merging [REDACTED_TASK_KEY]
)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.padding(
vertical = TangemTheme.dimens.spacing16,
)
.clip(TangemTheme.shapes.roundedCornersXMedium)
.background(TangemTheme.colors.background.primary),
state = listState,
item(
key = "title",
) {
item(
key = "title",
) {
Title()
}
items(
items = state.networks,
key = NFTNetworkUM::id,
) { network ->
NFTNetwork(state = network)
}
Title()
}
items(
items = state.items,
key = NFTNetworkUM::id,
) { network ->
NFTNetwork(
state = network,
modifier = Modifier.animateItem(),
)
}
}
}
@ -91,16 +72,9 @@ private fun Title(modifier: Modifier = Modifier) {
@Composable
private fun Preview_NFTReceiveNetworksUM() {
TangemThemePreview {
NFTReceiveNetworks(
state = NFTReceiveNetworksUM(
searchBar = SearchBarUM(
placeholderText = resourceReference(R.string.common_search),
query = "",
onQueryChange = { },
isActive = false,
onActiveChange = { },
),
networks = persistentListOf(
NFTReceiveNetworksContent(
state = NFTReceiveUM.Networks.Content(
items = persistentListOf(
NFTNetworkUM(
id = "item1",
name = "Ethereum",

View file

@ -0,0 +1,18 @@
package com.tangem.features.nft.receive.ui
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.tangem.core.ui.extensions.stringResourceSafe
import com.tangem.core.ui.res.TangemTheme
import com.tangem.features.nft.impl.R
@Composable
internal fun NFTReceiveNetworksEmpty(modifier: Modifier = Modifier) {
Text(
modifier = modifier,
text = stringResourceSafe(id = R.string.nft_empty_search),
style = TangemTheme.typography.body2,
color = TangemTheme.colors.text.tertiary,
)
}