Updated on 2026-08-14

This commit is contained in:
Tangem 2024-10-29 12:14:56 +04:00
parent 42b8de7909
commit 06f2d51e87
8 changed files with 130 additions and 8 deletions

View file

@ -11,6 +11,7 @@ import com.tangem.features.disclaimer.api.components.DisclaimerComponent
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.onramp.component.BuyCryptoComponent
import com.tangem.features.onramp.component.OnrampComponent
import com.tangem.features.pushnotifications.api.navigation.PushNotificationsRouter
import com.tangem.features.send.api.navigation.SendRouter
@ -48,6 +49,7 @@ internal class ChildFactory @Inject constructor(
private val manageTokensComponentFactory: ManageTokensComponent.Factory,
private val marketsTokenDetailsComponentFactory: MarketsTokenDetailsComponent.Factory,
private val onrampComponentFactory: OnrampComponent.Factory,
private val buyCryptoComponentFactory: BuyCryptoComponent.Factory,
private val sendRouter: SendRouter,
private val tokenDetailsRouter: TokenDetailsRouter,
private val walletRouter: WalletRouter,
@ -195,6 +197,13 @@ internal class ChildFactory @Inject constructor(
componentFactory = onrampComponentFactory,
)
}
is AppRoute.BuyCrypto -> {
route.asComponentChild(
contextProvider = contextProvider(route, contextFactory),
params = BuyCryptoComponent.Params(userWalletId = route.userWalletId),
componentFactory = buyCryptoComponentFactory,
)
}
}
}

View file

@ -117,10 +117,6 @@ sealed class AppRoute(val path: String) : Route {
) : AppRoute(path = "/details/security"), RouteBundleParams {
override fun getBundle(): Bundle = bundle(serializer())
companion object {
const val USER_WALLET_ID_KEY = "userWalletId"
}
}
@Serializable
@ -291,4 +287,9 @@ sealed class AppRoute(val path: String) : Route {
@Serializable
data object Onramp : AppRoute(path = "/onramp")
@Serializable
data class BuyCrypto(
val userWalletId: UserWalletId,
) : AppRoute(path = "/buy_crypto/${userWalletId.stringValue}")
}

View file

@ -6,10 +6,7 @@ import arrow.core.right
import com.tangem.domain.appcurrency.error.SelectedAppCurrencyError
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEmpty
import kotlinx.coroutines.flow.*
class GetSelectedAppCurrencyUseCase(
private val appCurrencyRepository: AppCurrencyRepository,
@ -21,4 +18,8 @@ class GetSelectedAppCurrencyUseCase(
.catch { emit(SelectedAppCurrencyError.DataError(it).left()) }
.onEmpty { emit(SelectedAppCurrencyError.NoAppCurrencySelected.left()) }
}
suspend fun invokeSync(): Either<SelectedAppCurrencyError, AppCurrency> {
return invoke().firstOrNull() ?: SelectedAppCurrencyError.NoAppCurrencySelected.left()
}
}

View file

@ -14,6 +14,9 @@ dependencies {
implementation(projects.core.decompose)
implementation(projects.core.ui)
/* Project - Domain */
implementation(projects.domain.wallets.models)
/* Compose */
implementation(deps.compose.runtime)
}

View file

@ -0,0 +1,22 @@
package com.tangem.features.onramp.component
import com.tangem.core.decompose.factory.ComponentFactory
import com.tangem.core.ui.decompose.ComposableContentComponent
import com.tangem.domain.wallets.models.UserWalletId
/**
* Buy crypto component
*
[REDACTED_AUTHOR]
*/
interface BuyCryptoComponent : ComposableContentComponent {
interface Factory : ComponentFactory<Params, BuyCryptoComponent>
/**
* Params
*
* @property userWalletId user wallet id
*/
data class Params(val userWalletId: UserWalletId)
}

View file

@ -28,8 +28,10 @@ dependencies {
implementation(projects.domain.appCurrency.models)
implementation(projects.domain.balanceHiding)
implementation(projects.domain.balanceHiding.models)
implementation(projects.domain.legacy)
implementation(projects.domain.tokens)
implementation(projects.domain.tokens.models)
implementation(projects.domain.wallets)
implementation(projects.domain.wallets.models)
/** DI */
@ -54,5 +56,6 @@ dependencies {
/** Other */
implementation(deps.decompose.ext.compose)
implementation(deps.kotlin.immutable.collections)
implementation(deps.reKotlin)
implementation(deps.timber)
}

View file

@ -0,0 +1,65 @@
package com.tangem.features.onramp.buy
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import arrow.core.getOrElse
import com.tangem.core.decompose.context.AppComponentContext
import com.tangem.domain.appcurrency.GetSelectedAppCurrencyUseCase
import com.tangem.domain.appcurrency.model.AppCurrency
import com.tangem.domain.redux.ReduxStateHolder
import com.tangem.domain.tokens.legacy.TradeCryptoAction
import com.tangem.domain.tokens.model.CryptoCurrencyStatus
import com.tangem.domain.wallets.usecase.GetWalletsUseCase
import com.tangem.features.onramp.component.BuyCryptoComponent
import com.tangem.features.onramp.impl.R
import com.tangem.features.onramp.selecttoken.OnrampSelectTokenComponent
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import kotlinx.coroutines.launch
@Stable
internal class DefaultBuyCryptoComponent @AssistedInject constructor(
onrampSelectTokenComponentFactory: OnrampSelectTokenComponent.Factory,
@Assisted private val appComponentContext: AppComponentContext,
@Assisted private val params: BuyCryptoComponent.Params,
private val reduxStateHolder: ReduxStateHolder,
private val getWalletsUseCase: GetWalletsUseCase,
private val getSelectedAppCurrencyUseCase: GetSelectedAppCurrencyUseCase,
) : BuyCryptoComponent {
private val selectTokenComponent: OnrampSelectTokenComponent = onrampSelectTokenComponentFactory.create(
context = appComponentContext,
params = OnrampSelectTokenComponent.Params(
hasSearchBar = true,
userWalletId = params.userWalletId,
titleResId = R.string.common_buy,
onTokenClick = ::onTokenClick,
),
)
@Composable
override fun Content(modifier: Modifier) {
selectTokenComponent.Content(modifier = modifier)
}
private fun onTokenClick(status: CryptoCurrencyStatus) {
appComponentContext.componentScope.launch {
reduxStateHolder.dispatch(
TradeCryptoAction.Buy(
userWallet = getWalletsUseCase.invokeSync().first { it.walletId == params.userWalletId },
cryptoCurrencyStatus = status,
appCurrencyCode = getSelectedAppCurrencyUseCase.invokeSync()
.getOrElse { AppCurrency.Default }.code,
),
)
}
}
@AssistedFactory
interface Factory : BuyCryptoComponent.Factory {
override fun create(context: AppComponentContext, params: BuyCryptoComponent.Params): DefaultBuyCryptoComponent
}
}

View file

@ -0,0 +1,18 @@
package com.tangem.features.onramp.buy.di
import com.tangem.features.onramp.buy.DefaultBuyCryptoComponent
import com.tangem.features.onramp.component.BuyCryptoComponent
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal interface BuyCryptoComponentModule {
@Binds
@Singleton
fun bindBuyCryptoComponentFactory(factory: DefaultBuyCryptoComponent.Factory): BuyCryptoComponent.Factory
}