Updated on 2026-08-14
This commit is contained in:
parent
7a45703d68
commit
c1d4bf79cb
15 changed files with 188 additions and 6 deletions
|
|
@ -13,6 +13,7 @@ import com.tangem.features.managetokens.component.ManageTokensComponent
|
||||||
import com.tangem.features.managetokens.component.ManageTokensSource
|
import com.tangem.features.managetokens.component.ManageTokensSource
|
||||||
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
import com.tangem.features.markets.details.MarketsTokenDetailsComponent
|
||||||
import com.tangem.features.nft.component.NFTCollectionsComponent
|
import com.tangem.features.nft.component.NFTCollectionsComponent
|
||||||
|
import com.tangem.features.nft.component.NFTDetailsComponent
|
||||||
import com.tangem.features.nft.component.NFTReceiveComponent
|
import com.tangem.features.nft.component.NFTReceiveComponent
|
||||||
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
import com.tangem.features.onboarding.v2.entry.OnboardingEntryComponent
|
||||||
import com.tangem.features.onramp.component.*
|
import com.tangem.features.onramp.component.*
|
||||||
|
|
@ -84,6 +85,7 @@ internal class ChildFactory @Inject constructor(
|
||||||
private val redesignedWalletConnectComponentFactory: RedisegnedWalletConnectComponent.Factory,
|
private val redesignedWalletConnectComponentFactory: RedisegnedWalletConnectComponent.Factory,
|
||||||
private val nftCollectionsComponentFactory: NFTCollectionsComponent.Factory,
|
private val nftCollectionsComponentFactory: NFTCollectionsComponent.Factory,
|
||||||
private val nftReceiveComponentFactory: NFTReceiveComponent.Factory,
|
private val nftReceiveComponentFactory: NFTReceiveComponent.Factory,
|
||||||
|
private val nftDetailsComponentFactory: NFTDetailsComponent.Factory,
|
||||||
private val testerRouter: TesterRouter,
|
private val testerRouter: TesterRouter,
|
||||||
private val routingFeatureToggles: RoutingFeatureToggles,
|
private val routingFeatureToggles: RoutingFeatureToggles,
|
||||||
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||||
|
|
@ -415,6 +417,12 @@ internal class ChildFactory @Inject constructor(
|
||||||
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
||||||
componentFactory = nftReceiveComponentFactory,
|
componentFactory = nftReceiveComponentFactory,
|
||||||
)
|
)
|
||||||
|
is AppRoute.NFTDetails ->
|
||||||
|
createComponentChild(
|
||||||
|
context = context,
|
||||||
|
params = NFTDetailsComponent.Params(userWalletId = route.userWalletId, nftAsset = route.nftAsset),
|
||||||
|
componentFactory = nftDetailsComponentFactory,
|
||||||
|
)
|
||||||
is AppRoute.OnboardingNote,
|
is AppRoute.OnboardingNote,
|
||||||
is AppRoute.SaveWallet,
|
is AppRoute.SaveWallet,
|
||||||
is AppRoute.OnboardingOther,
|
is AppRoute.OnboardingOther,
|
||||||
|
|
@ -761,6 +769,12 @@ internal class ChildFactory @Inject constructor(
|
||||||
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
||||||
componentFactory = nftReceiveComponentFactory,
|
componentFactory = nftReceiveComponentFactory,
|
||||||
)
|
)
|
||||||
|
is AppRoute.NFTDetails ->
|
||||||
|
route.asComponentChild(
|
||||||
|
contextProvider = contextProvider(route, contextFactory),
|
||||||
|
params = NFTDetailsComponent.Params(userWalletId = route.userWalletId, nftAsset = route.nftAsset),
|
||||||
|
componentFactory = nftDetailsComponentFactory,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ dependencies {
|
||||||
implementation(projects.domain.markets.models)
|
implementation(projects.domain.markets.models)
|
||||||
implementation(projects.domain.onramp.models)
|
implementation(projects.domain.onramp.models)
|
||||||
implementation(projects.domain.appCurrency.models)
|
implementation(projects.domain.appCurrency.models)
|
||||||
|
implementation(projects.domain.nft.models)
|
||||||
|
|
||||||
/* Libs - Other */
|
/* Libs - Other */
|
||||||
api(deps.kotlin.serialization)
|
api(deps.kotlin.serialization)
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import com.tangem.core.decompose.navigation.Route
|
||||||
import com.tangem.domain.appcurrency.model.AppCurrency
|
import com.tangem.domain.appcurrency.model.AppCurrency
|
||||||
import com.tangem.domain.markets.TokenMarketParams
|
import com.tangem.domain.markets.TokenMarketParams
|
||||||
import com.tangem.domain.models.scan.ScanResponse
|
import com.tangem.domain.models.scan.ScanResponse
|
||||||
|
import com.tangem.domain.nft.models.NFTAsset
|
||||||
import com.tangem.domain.onramp.model.OnrampSource
|
import com.tangem.domain.onramp.model.OnrampSource
|
||||||
import com.tangem.domain.tokens.model.CryptoCurrency
|
import com.tangem.domain.tokens.model.CryptoCurrency
|
||||||
import com.tangem.domain.wallets.models.UserWalletId
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
@ -288,4 +289,10 @@ sealed class AppRoute(val path: String) : Route {
|
||||||
data class NFTReceive(
|
data class NFTReceive(
|
||||||
val userWalletId: UserWalletId,
|
val userWalletId: UserWalletId,
|
||||||
) : AppRoute(path = "/nft_receive/${userWalletId.stringValue}")
|
) : AppRoute(path = "/nft_receive/${userWalletId.stringValue}")
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class NFTDetails(
|
||||||
|
val userWalletId: UserWalletId,
|
||||||
|
val nftAsset: NFTAsset,
|
||||||
|
) : AppRoute(path = "/nft_details/${userWalletId.stringValue}/${nftAsset.collectionId}/${nftAsset.id.stringValue}")
|
||||||
}
|
}
|
||||||
1
domain/networks/.gitignore
vendored
Normal file
1
domain/networks/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
||||||
|
|
@ -8,7 +8,10 @@ dependencies {
|
||||||
implementation(deps.arrow.core)
|
implementation(deps.arrow.core)
|
||||||
implementation(deps.kotlin.coroutines)
|
implementation(deps.kotlin.coroutines)
|
||||||
|
|
||||||
|
implementation(projects.domain.core)
|
||||||
implementation(projects.domain.models)
|
implementation(projects.domain.models)
|
||||||
|
|
||||||
implementation(projects.domain.tokens.models)
|
implementation(projects.domain.tokens.models)
|
||||||
|
|
||||||
|
/* Utils */
|
||||||
|
implementation(deps.kotlin.serialization)
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,9 @@ package com.tangem.domain.nft.models
|
||||||
|
|
||||||
import com.tangem.domain.models.StatusSource
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class NFTAsset(
|
data class NFTAsset(
|
||||||
val id: Identifier,
|
val id: Identifier,
|
||||||
val collectionId: NFTCollection.Identifier,
|
val collectionId: NFTCollection.Identifier,
|
||||||
|
|
@ -18,29 +20,44 @@ data class NFTAsset(
|
||||||
val source: StatusSource,
|
val source: StatusSource,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Media(
|
data class Media(
|
||||||
val mimetype: String?,
|
val mimetype: String?,
|
||||||
val url: String,
|
val url: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Rarity(
|
data class Rarity(
|
||||||
val rank: String,
|
val rank: String,
|
||||||
val label: String,
|
val label: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Trait(
|
data class Trait(
|
||||||
val name: String,
|
val name: String,
|
||||||
val value: String,
|
val value: String,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed class Identifier {
|
sealed class Identifier {
|
||||||
|
abstract val stringValue: String
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class EVM(
|
data class EVM(
|
||||||
val tokenId: String,
|
val tokenId: String,
|
||||||
val tokenAddress: String,
|
val tokenAddress: String,
|
||||||
) : Identifier()
|
) : Identifier() {
|
||||||
|
override val stringValue: String = "${tokenAddress}_$tokenId"
|
||||||
|
}
|
||||||
|
|
||||||
data class TON(val tokenAddress: String) : Identifier()
|
@Serializable
|
||||||
|
data class TON(val tokenAddress: String) : Identifier() {
|
||||||
|
override val stringValue: String = tokenAddress
|
||||||
|
}
|
||||||
|
|
||||||
data object Unknown : Identifier()
|
@Serializable
|
||||||
|
data object Unknown : Identifier() {
|
||||||
|
override val stringValue: String = ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,9 @@ package com.tangem.domain.nft.models
|
||||||
|
|
||||||
import com.tangem.domain.models.StatusSource
|
import com.tangem.domain.models.StatusSource
|
||||||
import com.tangem.domain.tokens.model.Network
|
import com.tangem.domain.tokens.model.Network
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class NFTCollection(
|
data class NFTCollection(
|
||||||
val id: Identifier,
|
val id: Identifier,
|
||||||
val network: Network,
|
val network: Network,
|
||||||
|
|
@ -12,19 +14,33 @@ data class NFTCollection(
|
||||||
val count: Int,
|
val count: Int,
|
||||||
val assets: Assets,
|
val assets: Assets,
|
||||||
) {
|
) {
|
||||||
|
@Serializable
|
||||||
sealed class Assets {
|
sealed class Assets {
|
||||||
|
@Serializable
|
||||||
data object Empty : Assets()
|
data object Empty : Assets()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data object Loading : Assets()
|
data object Loading : Assets()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data object Failed : Assets()
|
data object Failed : Assets()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Value(
|
data class Value(
|
||||||
val items: List<NFTAsset>,
|
val items: List<NFTAsset>,
|
||||||
val source: StatusSource,
|
val source: StatusSource,
|
||||||
) : Assets()
|
) : Assets()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed class Identifier {
|
sealed class Identifier {
|
||||||
|
@Serializable
|
||||||
data class EVM(val tokenAddress: String) : Identifier()
|
data class EVM(val tokenAddress: String) : Identifier()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class TON(val contractAddress: String?) : Identifier()
|
data class TON(val contractAddress: String?) : Identifier()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data object Unknown : Identifier()
|
data object Unknown : Identifier()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,25 +1,31 @@
|
||||||
package com.tangem.domain.nft.models
|
package com.tangem.domain.nft.models
|
||||||
|
|
||||||
import java.math.BigDecimal
|
import com.tangem.domain.core.serialization.SerializedBigDecimal
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
sealed class NFTSalePrice {
|
sealed class NFTSalePrice {
|
||||||
abstract val assetId: NFTAsset.Identifier
|
abstract val assetId: NFTAsset.Identifier
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Empty(
|
data class Empty(
|
||||||
override val assetId: NFTAsset.Identifier,
|
override val assetId: NFTAsset.Identifier,
|
||||||
) : NFTSalePrice()
|
) : NFTSalePrice()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Loading(
|
data class Loading(
|
||||||
override val assetId: NFTAsset.Identifier,
|
override val assetId: NFTAsset.Identifier,
|
||||||
) : NFTSalePrice()
|
) : NFTSalePrice()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Error(
|
data class Error(
|
||||||
override val assetId: NFTAsset.Identifier,
|
override val assetId: NFTAsset.Identifier,
|
||||||
) : NFTSalePrice()
|
) : NFTSalePrice()
|
||||||
|
|
||||||
|
@Serializable
|
||||||
data class Value(
|
data class Value(
|
||||||
override val assetId: NFTAsset.Identifier,
|
override val assetId: NFTAsset.Identifier,
|
||||||
val value: BigDecimal,
|
val value: SerializedBigDecimal,
|
||||||
val symbol: String,
|
val symbol: String,
|
||||||
) : NFTSalePrice()
|
) : NFTSalePrice()
|
||||||
}
|
}
|
||||||
|
|
@ -12,6 +12,7 @@ dependencies {
|
||||||
|
|
||||||
/* Project - Domain */
|
/* Project - Domain */
|
||||||
implementation(projects.domain.models)
|
implementation(projects.domain.models)
|
||||||
|
implementation(projects.domain.nft.models)
|
||||||
implementation(projects.domain.wallets.models)
|
implementation(projects.domain.wallets.models)
|
||||||
|
|
||||||
/* Project - Core */
|
/* Project - Core */
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.tangem.features.nft.component
|
||||||
|
|
||||||
|
import com.tangem.core.decompose.factory.ComponentFactory
|
||||||
|
import com.tangem.core.ui.decompose.ComposableContentComponent
|
||||||
|
import com.tangem.domain.nft.models.NFTAsset
|
||||||
|
import com.tangem.domain.wallets.models.UserWalletId
|
||||||
|
|
||||||
|
interface NFTDetailsComponent : ComposableContentComponent {
|
||||||
|
|
||||||
|
data class Params(
|
||||||
|
val userWalletId: UserWalletId,
|
||||||
|
val nftAsset: NFTAsset,
|
||||||
|
)
|
||||||
|
|
||||||
|
interface Factory : ComponentFactory<Params, NFTDetailsComponent>
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,10 @@ import com.tangem.core.decompose.model.Model
|
||||||
import com.tangem.features.nft.collections.DefaultNFTCollectionsComponent
|
import com.tangem.features.nft.collections.DefaultNFTCollectionsComponent
|
||||||
import com.tangem.features.nft.collections.model.NFTCollectionsModel
|
import com.tangem.features.nft.collections.model.NFTCollectionsModel
|
||||||
import com.tangem.features.nft.component.NFTCollectionsComponent
|
import com.tangem.features.nft.component.NFTCollectionsComponent
|
||||||
|
import com.tangem.features.nft.component.NFTDetailsComponent
|
||||||
import com.tangem.features.nft.component.NFTReceiveComponent
|
import com.tangem.features.nft.component.NFTReceiveComponent
|
||||||
|
import com.tangem.features.nft.details.DefaultNFTDetailsComponent
|
||||||
|
import com.tangem.features.nft.details.model.NFTDetailsModel
|
||||||
import com.tangem.features.nft.receive.DefaultNFTReceiveComponent
|
import com.tangem.features.nft.receive.DefaultNFTReceiveComponent
|
||||||
import com.tangem.features.nft.receive.model.NFTReceiveModel
|
import com.tangem.features.nft.receive.model.NFTReceiveModel
|
||||||
import dagger.Binds
|
import dagger.Binds
|
||||||
|
|
@ -50,4 +53,13 @@ internal interface NFTFeatureModuleBinds {
|
||||||
@IntoMap
|
@IntoMap
|
||||||
@ClassKey(NFTReceiveModel::class)
|
@ClassKey(NFTReceiveModel::class)
|
||||||
fun bindNFTReceiveModel(model: NFTReceiveModel): Model
|
fun bindNFTReceiveModel(model: NFTReceiveModel): Model
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@Singleton
|
||||||
|
fun bindNFTDetailsComponentFactory(impl: DefaultNFTDetailsComponent.Factory): NFTDetailsComponent.Factory
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ClassKey(NFTDetailsModel::class)
|
||||||
|
fun bindNFTDetailsModel(model: NFTDetailsModel): Model
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.tangem.features.nft.details
|
||||||
|
|
||||||
|
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.NFTDetailsComponent
|
||||||
|
import com.tangem.features.nft.details.model.NFTDetailsModel
|
||||||
|
import com.tangem.features.nft.details.ui.NFTDetails
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedFactory
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
|
|
||||||
|
internal class DefaultNFTDetailsComponent @AssistedInject constructor(
|
||||||
|
@Assisted context: AppComponentContext,
|
||||||
|
@Assisted private val params: NFTDetailsComponent.Params,
|
||||||
|
) : NFTDetailsComponent, AppComponentContext by context {
|
||||||
|
|
||||||
|
private val model: NFTDetailsModel = getOrCreateModel(params)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun Content(modifier: Modifier) {
|
||||||
|
val state by model.state.collectAsStateWithLifecycle()
|
||||||
|
|
||||||
|
NFTDetails(state, modifier)
|
||||||
|
}
|
||||||
|
|
||||||
|
@AssistedFactory
|
||||||
|
interface Factory : NFTDetailsComponent.Factory {
|
||||||
|
override fun create(
|
||||||
|
context: AppComponentContext,
|
||||||
|
params: NFTDetailsComponent.Params,
|
||||||
|
): DefaultNFTDetailsComponent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.tangem.features.nft.details.entity
|
||||||
|
|
||||||
|
internal data class NFTDetailsUM(
|
||||||
|
val onBackClick: () -> Unit,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.tangem.features.nft.details.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.features.nft.component.NFTDetailsComponent
|
||||||
|
import com.tangem.features.nft.details.entity.NFTDetailsUM
|
||||||
|
import com.tangem.utils.coroutines.CoroutineDispatcherProvider
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@ModelScoped
|
||||||
|
internal class NFTDetailsModel @Inject constructor(
|
||||||
|
override val dispatchers: CoroutineDispatcherProvider,
|
||||||
|
private val router: Router,
|
||||||
|
paramsContainer: ParamsContainer,
|
||||||
|
) : Model() {
|
||||||
|
|
||||||
|
val state: StateFlow<NFTDetailsUM> get() = _state
|
||||||
|
|
||||||
|
private val _state = MutableStateFlow(
|
||||||
|
value = NFTDetailsUM(
|
||||||
|
onBackClick = ::navigateBack,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Suppress("UnusedPrivateMember")
|
||||||
|
private val params: NFTDetailsComponent.Params = paramsContainer.require()
|
||||||
|
|
||||||
|
private fun navigateBack() {
|
||||||
|
router.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.tangem.features.nft.details.ui
|
||||||
|
|
||||||
|
import androidx.activity.compose.BackHandler
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import com.tangem.features.nft.details.entity.NFTDetailsUM
|
||||||
|
|
||||||
|
@Suppress("UnusedPrivateMember")
|
||||||
|
@Composable
|
||||||
|
internal fun NFTDetails(state: NFTDetailsUM, modifier: Modifier = Modifier) {
|
||||||
|
BackHandler(onBack = state.onBackClick)
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue