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.markets.details.MarketsTokenDetailsComponent
|
||||
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.onboarding.v2.entry.OnboardingEntryComponent
|
||||
import com.tangem.features.onramp.component.*
|
||||
|
|
@ -84,6 +85,7 @@ internal class ChildFactory @Inject constructor(
|
|||
private val redesignedWalletConnectComponentFactory: RedisegnedWalletConnectComponent.Factory,
|
||||
private val nftCollectionsComponentFactory: NFTCollectionsComponent.Factory,
|
||||
private val nftReceiveComponentFactory: NFTReceiveComponent.Factory,
|
||||
private val nftDetailsComponentFactory: NFTDetailsComponent.Factory,
|
||||
private val testerRouter: TesterRouter,
|
||||
private val routingFeatureToggles: RoutingFeatureToggles,
|
||||
private val walletConnectFeatureToggles: WalletConnectFeatureToggles,
|
||||
|
|
@ -415,6 +417,12 @@ internal class ChildFactory @Inject constructor(
|
|||
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
||||
componentFactory = nftReceiveComponentFactory,
|
||||
)
|
||||
is AppRoute.NFTDetails ->
|
||||
createComponentChild(
|
||||
context = context,
|
||||
params = NFTDetailsComponent.Params(userWalletId = route.userWalletId, nftAsset = route.nftAsset),
|
||||
componentFactory = nftDetailsComponentFactory,
|
||||
)
|
||||
is AppRoute.OnboardingNote,
|
||||
is AppRoute.SaveWallet,
|
||||
is AppRoute.OnboardingOther,
|
||||
|
|
@ -761,6 +769,12 @@ internal class ChildFactory @Inject constructor(
|
|||
params = NFTReceiveComponent.Params(userWalletId = route.userWalletId),
|
||||
componentFactory = nftReceiveComponentFactory,
|
||||
)
|
||||
is AppRoute.NFTDetails ->
|
||||
route.asComponentChild(
|
||||
contextProvider = contextProvider(route, contextFactory),
|
||||
params = NFTDetailsComponent.Params(userWalletId = route.userWalletId, nftAsset = route.nftAsset),
|
||||
componentFactory = nftDetailsComponentFactory,
|
||||
)
|
||||
}
|
||||
// endregion
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ dependencies {
|
|||
implementation(projects.domain.markets.models)
|
||||
implementation(projects.domain.onramp.models)
|
||||
implementation(projects.domain.appCurrency.models)
|
||||
implementation(projects.domain.nft.models)
|
||||
|
||||
/* Libs - Other */
|
||||
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.markets.TokenMarketParams
|
||||
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.tokens.model.CryptoCurrency
|
||||
import com.tangem.domain.wallets.models.UserWalletId
|
||||
|
|
@ -288,4 +289,10 @@ sealed class AppRoute(val path: String) : Route {
|
|||
data class NFTReceive(
|
||||
val userWalletId: UserWalletId,
|
||||
) : 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.kotlin.coroutines)
|
||||
|
||||
implementation(projects.domain.core)
|
||||
implementation(projects.domain.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.tokens.model.Network
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NFTAsset(
|
||||
val id: Identifier,
|
||||
val collectionId: NFTCollection.Identifier,
|
||||
|
|
@ -18,29 +20,44 @@ data class NFTAsset(
|
|||
val source: StatusSource,
|
||||
) {
|
||||
|
||||
@Serializable
|
||||
data class Media(
|
||||
val mimetype: String?,
|
||||
val url: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Rarity(
|
||||
val rank: String,
|
||||
val label: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class Trait(
|
||||
val name: String,
|
||||
val value: String,
|
||||
)
|
||||
|
||||
@Serializable
|
||||
sealed class Identifier {
|
||||
abstract val stringValue: String
|
||||
|
||||
@Serializable
|
||||
data class EVM(
|
||||
val tokenId: 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.tokens.model.Network
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class NFTCollection(
|
||||
val id: Identifier,
|
||||
val network: Network,
|
||||
|
|
@ -12,19 +14,33 @@ data class NFTCollection(
|
|||
val count: Int,
|
||||
val assets: Assets,
|
||||
) {
|
||||
@Serializable
|
||||
sealed class Assets {
|
||||
@Serializable
|
||||
data object Empty : Assets()
|
||||
|
||||
@Serializable
|
||||
data object Loading : Assets()
|
||||
|
||||
@Serializable
|
||||
data object Failed : Assets()
|
||||
|
||||
@Serializable
|
||||
data class Value(
|
||||
val items: List<NFTAsset>,
|
||||
val source: StatusSource,
|
||||
) : Assets()
|
||||
}
|
||||
|
||||
@Serializable
|
||||
sealed class Identifier {
|
||||
@Serializable
|
||||
data class EVM(val tokenAddress: String) : Identifier()
|
||||
|
||||
@Serializable
|
||||
data class TON(val contractAddress: String?) : Identifier()
|
||||
|
||||
@Serializable
|
||||
data object Unknown : Identifier()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +1,31 @@
|
|||
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 {
|
||||
abstract val assetId: NFTAsset.Identifier
|
||||
|
||||
@Serializable
|
||||
data class Empty(
|
||||
override val assetId: NFTAsset.Identifier,
|
||||
) : NFTSalePrice()
|
||||
|
||||
@Serializable
|
||||
data class Loading(
|
||||
override val assetId: NFTAsset.Identifier,
|
||||
) : NFTSalePrice()
|
||||
|
||||
@Serializable
|
||||
data class Error(
|
||||
override val assetId: NFTAsset.Identifier,
|
||||
) : NFTSalePrice()
|
||||
|
||||
@Serializable
|
||||
data class Value(
|
||||
override val assetId: NFTAsset.Identifier,
|
||||
val value: BigDecimal,
|
||||
val value: SerializedBigDecimal,
|
||||
val symbol: String,
|
||||
) : NFTSalePrice()
|
||||
}
|
||||
|
|
@ -12,6 +12,7 @@ dependencies {
|
|||
|
||||
/* Project - Domain */
|
||||
implementation(projects.domain.models)
|
||||
implementation(projects.domain.nft.models)
|
||||
implementation(projects.domain.wallets.models)
|
||||
|
||||
/* 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.model.NFTCollectionsModel
|
||||
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.details.DefaultNFTDetailsComponent
|
||||
import com.tangem.features.nft.details.model.NFTDetailsModel
|
||||
import com.tangem.features.nft.receive.DefaultNFTReceiveComponent
|
||||
import com.tangem.features.nft.receive.model.NFTReceiveModel
|
||||
import dagger.Binds
|
||||
|
|
@ -50,4 +53,13 @@ internal interface NFTFeatureModuleBinds {
|
|||
@IntoMap
|
||||
@ClassKey(NFTReceiveModel::class)
|
||||
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