Updated on 2026-08-14
This commit is contained in:
commit
64fab92d06
231 changed files with 5317 additions and 1797 deletions
|
|
@ -26,6 +26,7 @@ import com.tangem.domain.DomainLayer
|
|||
import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
||||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.common.LogConfig
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.WalletManagersRepository
|
||||
import com.tangem.feature.learn2earn.domain.api.Learn2earnInteractor
|
||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||
|
|
@ -42,6 +43,7 @@ import com.tangem.tap.common.feedback.AdditionalFeedbackInfo
|
|||
import com.tangem.tap.common.feedback.FeedbackManager
|
||||
import com.tangem.tap.common.images.createCoilImageLoader
|
||||
import com.tangem.tap.common.log.TangemLogCollector
|
||||
import com.tangem.tap.common.log.TimberFormatStrategy
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.appReducer
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
@ -165,6 +167,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
@Inject
|
||||
lateinit var appCurrencyRepository: AppCurrencyRepository
|
||||
|
||||
@Inject
|
||||
lateinit var walletManagersFacade: WalletManagersFacade
|
||||
|
||||
override fun onCreate() {
|
||||
super.onCreate()
|
||||
|
||||
|
|
@ -184,12 +189,13 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
tokenDetailsFeatureToggles = tokenDetailsFeatureToggles,
|
||||
scanCardProcessor = scanCardProcessor,
|
||||
appCurrencyRepository = appCurrencyRepository,
|
||||
walletManagersFacade = walletManagersFacade,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Logger.addLogAdapter(AndroidLogAdapter())
|
||||
Logger.addLogAdapter(AndroidLogAdapter(TimberFormatStrategy()))
|
||||
Timber.plant(
|
||||
object : Timber.DebugTree() {
|
||||
override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
package com.tangem.tap.common.apptheme
|
||||
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.domain.apptheme.model.AppThemeMode
|
||||
|
||||
internal object MutableAppThemeModeHolder : AppThemeModeHolder {
|
||||
|
||||
override val appThemeMode: MutableState<AppThemeMode> = mutableStateOf(AppThemeMode.DEFAULT)
|
||||
|
||||
var value: AppThemeMode
|
||||
set(value) {
|
||||
appThemeMode.value = value
|
||||
}
|
||||
get() = appThemeMode.value
|
||||
}
|
||||
|
|
@ -82,7 +82,7 @@ fun WalletManager?.getAddressData(): WalletDataModel.AddressData? {
|
|||
}
|
||||
|
||||
fun <T> WalletManager.Companion.stub(): T {
|
||||
val wallet = Wallet(Blockchain.Unknown, setOf(), Wallet.PublicKey(byteArrayOf(), null, null), setOf())
|
||||
val wallet = Wallet(Blockchain.Unknown, setOf(), Wallet.PublicKey(byteArrayOf(), null), setOf())
|
||||
return object : WalletManager(wallet) {
|
||||
override val currentHost: String = ""
|
||||
override suspend fun update() {}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
package com.tangem.tap.common.log
|
||||
|
||||
import com.orhanobut.logger.FormatStrategy
|
||||
import com.orhanobut.logger.LogStrategy
|
||||
import com.orhanobut.logger.LogcatLogStrategy
|
||||
|
||||
class TimberFormatStrategy : FormatStrategy {
|
||||
|
||||
private val logStrategy: LogStrategy = LogcatLogStrategy()
|
||||
|
||||
override fun log(priority: Int, tag: String?, message: String) {
|
||||
logTopBorder(priority, tag)
|
||||
val bytes = message.toByteArray()
|
||||
val length = bytes.size
|
||||
if (length <= CHUNK_SIZE) {
|
||||
logContent(priority, tag, message)
|
||||
logBottomBorder(priority, tag)
|
||||
return
|
||||
}
|
||||
var i = 0
|
||||
while (i < length) {
|
||||
val count = (length - i).coerceAtMost(CHUNK_SIZE)
|
||||
// create a new String with system's default charset (which is UTF-8 for Android)
|
||||
logContent(priority, tag, String(bytes, i, count))
|
||||
i += CHUNK_SIZE
|
||||
}
|
||||
logBottomBorder(priority, tag)
|
||||
}
|
||||
|
||||
private fun logTopBorder(logType: Int, tag: String?) {
|
||||
logChunk(logType, tag, TOP_BORDER)
|
||||
}
|
||||
|
||||
private fun logBottomBorder(logType: Int, tag: String?) {
|
||||
logChunk(logType, tag, BOTTOM_BORDER)
|
||||
}
|
||||
|
||||
private fun logContent(logType: Int, tag: String?, chunk: String) {
|
||||
chunk.split(System.lineSeparator()).forEach { line ->
|
||||
logChunk(logType, tag, "$HORIZONTAL_LINE $line")
|
||||
}
|
||||
}
|
||||
|
||||
private fun logChunk(priority: Int, tag: String?, chunk: String) {
|
||||
logStrategy.log(priority, tag, chunk)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
/**
|
||||
* Android's max limit for a log entry is ~4076 bytes,
|
||||
* so 4000 bytes is used as chunk size since default charset
|
||||
* is UTF-8
|
||||
*/
|
||||
private const val CHUNK_SIZE = 4000
|
||||
|
||||
const val TOP_LEFT_CORNER = "┌"
|
||||
const val BOTTOM_LEFT_CORNER = "└"
|
||||
const val HORIZONTAL_LINE = "│"
|
||||
const val DOUBLE_DIVIDER = "────────────────────────────────────────────────────────"
|
||||
const val TOP_BORDER = TOP_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER
|
||||
const val BOTTOM_BORDER = BOTTOM_LEFT_CORNER + DOUBLE_DIVIDER + DOUBLE_DIVIDER
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package com.tangem.tap.di
|
||||
|
||||
import com.tangem.core.navigation.NavigationStateHolder
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.tap.proxy.AppStateHolder
|
||||
import dagger.Binds
|
||||
|
|
@ -20,4 +21,8 @@ internal interface AppStateHolderModule {
|
|||
@Binds
|
||||
@Singleton
|
||||
fun bindsNavigationStateHolder(appStateHolder: AppStateHolder): NavigationStateHolder
|
||||
|
||||
@Binds
|
||||
@Singleton
|
||||
fun bindsReduxStateHolder(appStateHolder: AppStateHolder): ReduxStateHolder
|
||||
}
|
||||
18
app/src/main/java/com/tangem/tap/di/ThemeModule.kt
Normal file
18
app/src/main/java/com/tangem/tap/di/ThemeModule.kt
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
package com.tangem.tap.di
|
||||
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.tap.common.apptheme.MutableAppThemeModeHolder
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ActivityComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(ActivityComponent::class)
|
||||
internal object ThemeModule {
|
||||
|
||||
@Provides
|
||||
fun provideAppThemeModeHolder(): AppThemeModeHolder {
|
||||
return MutableAppThemeModeHolder
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
package com.tangem.tap.di.domain
|
||||
|
||||
import com.tangem.domain.apptheme.ChangeAppThemeModeUseCase
|
||||
import com.tangem.domain.apptheme.GetAppThemeModeUseCase
|
||||
import com.tangem.domain.apptheme.repository.AppThemeModeRepository
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.android.components.ViewModelComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(ViewModelComponent::class)
|
||||
internal object AppThemeDomainModule {
|
||||
|
||||
@Provides
|
||||
fun provideGetAppThemeModeUpdatesUseCase(appThemeModeRepository: AppThemeModeRepository): GetAppThemeModeUseCase {
|
||||
return GetAppThemeModeUseCase(appThemeModeRepository)
|
||||
}
|
||||
|
||||
@Provides
|
||||
fun provideChangeAppThemeModeUseCase(appThemeModeRepository: AppThemeModeRepository): ChangeAppThemeModeUseCase {
|
||||
return ChangeAppThemeModeUseCase(appThemeModeRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -51,10 +51,9 @@ internal object TokensDomainModule {
|
|||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideToggleTokenListGroupingUseCase(
|
||||
networksRepository: NetworksRepository,
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): ToggleTokenListGroupingUseCase {
|
||||
return ToggleTokenListGroupingUseCase(networksRepository, dispatchers)
|
||||
return ToggleTokenListGroupingUseCase(dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
|
@ -71,4 +70,12 @@ internal object TokensDomainModule {
|
|||
): ApplyTokenListSortingUseCase {
|
||||
return ApplyTokenListSortingUseCase(currenciesRepository, dispatchers)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun provideGetCryptoCurrencyActionsUseCase(
|
||||
dispatchers: CoroutineDispatcherProvider,
|
||||
): GetCryptoCurrencyActionsUseCase {
|
||||
return GetCryptoCurrencyActionsUseCase(dispatchers)
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.di.domain
|
|||
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.domain.wallets.repository.WalletsRepository
|
||||
import com.tangem.domain.wallets.usecase.*
|
||||
import dagger.Module
|
||||
import dagger.Provides
|
||||
|
|
@ -48,4 +49,22 @@ internal object WalletsDomainModule {
|
|||
fun providesSelectWalletUseCase(walletsStateHolder: WalletsStateHolder): SelectWalletUseCase {
|
||||
return SelectWalletUseCase(walletsStateHolder = walletsStateHolder)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesUpdateWalletUseCase(walletsStateHolder: WalletsStateHolder): UpdateWalletUseCase {
|
||||
return UpdateWalletUseCase(walletsStateHolder = walletsStateHolder)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesDeleteWalletUseCase(walletsStateHolder: WalletsStateHolder): DeleteWalletUseCase {
|
||||
return DeleteWalletUseCase(walletsStateHolder = walletsStateHolder)
|
||||
}
|
||||
|
||||
@Provides
|
||||
@ViewModelScoped
|
||||
fun providesShouldSaveUserWalletsUseCase(walletsRepository: WalletsRepository): ShouldSaveUserWalletsUseCase {
|
||||
return ShouldSaveUserWalletsUseCase(walletsRepository = walletsRepository)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
package com.tangem.tap.domain.settings
|
||||
|
||||
import com.tangem.domain.settings.repositories.LegacySettingsRepository
|
||||
import com.tangem.tap.domain.TangemSdkManager
|
||||
|
||||
internal class DefaultLegacySettingsRepository(
|
||||
private val tangemSdkManager: TangemSdkManager,
|
||||
) : LegacySettingsRepository {
|
||||
|
||||
override fun canUseBiometry(): Boolean = tangemSdkManager.canUseBiometry
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.domain.tasks.product
|
||||
|
||||
import com.tangem.blockchain.blockchains.cardano.CardanoUtils
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.common.card.Card
|
||||
|
|
@ -224,7 +225,8 @@ private class ScanWalletProcessor(
|
|||
walletData = session.environment.walletData,
|
||||
primaryCard = primaryCard,
|
||||
)
|
||||
val derivations = collectDerivations(card, config, scanResponse.derivationStyleProvider)
|
||||
val derivations =
|
||||
collectDerivations(card, config, scanResponse.derivationStyleProvider)
|
||||
if (derivations.isEmpty() || !card.settings.isHDWalletAllowed) {
|
||||
callback(CompletionResult.Success(scanResponse))
|
||||
return@launch
|
||||
|
|
@ -249,60 +251,101 @@ private class ScanWalletProcessor(
|
|||
val userTokensRepository = userTokensRepository ?: return emptyList()
|
||||
val blockchainsToDerive = userTokensRepository.loadBlockchainsToDerive(card)
|
||||
.toMutableList()
|
||||
.ifEmpty {
|
||||
mutableListOf(
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Bitcoin,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
)
|
||||
}
|
||||
.ifEmpty { getDefaultBlockchains(derivationStyleProvider) }
|
||||
|
||||
if (card.settings.isHDWalletAllowed) {
|
||||
blockchainsToDerive.addAll(
|
||||
listOf(
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.EthereumTestnet,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
),
|
||||
)
|
||||
blockchainsToDerive += getEthereumBlockchains(derivationStyleProvider)
|
||||
}
|
||||
if (additionalBlockchainsToDerive != null) {
|
||||
blockchainsToDerive.addAll(
|
||||
additionalBlockchainsToDerive.map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
additionalBlockchainsToDerive?.let {
|
||||
blockchainsToDerive += getAdditionalBlockchainToDerive(derivationStyleProvider, it)
|
||||
}
|
||||
|
||||
// we should generate second key for cardano
|
||||
// because cardano address generation for wallet2 requires keys from 2 derivations
|
||||
// https://developers.cardano.org/docs/get-started/cardano-serialization-lib/generating-keys/
|
||||
val secondCardanoNetwork = blockchainsToDerive
|
||||
.find { it.blockchain == Blockchain.Cardano }
|
||||
?.let { getCardanoSecondNetwork(it) }
|
||||
secondCardanoNetwork?.let { blockchainsToDerive.add(it) }
|
||||
|
||||
// pay attention to this
|
||||
if (!card.useOldStyleDerivation) {
|
||||
blockchainsToDerive.removeAll(
|
||||
listOf(
|
||||
Blockchain.BSC, Blockchain.BSCTestnet,
|
||||
Blockchain.Polygon, Blockchain.PolygonTestnet,
|
||||
Blockchain.RSK,
|
||||
Blockchain.Fantom, Blockchain.FantomTestnet,
|
||||
Blockchain.Avalanche, Blockchain.AvalancheTestnet,
|
||||
).map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
},
|
||||
removeUnnecessaryBlockchains(blockchainsToDerive, derivationStyleProvider)
|
||||
}
|
||||
|
||||
return blockchainsToDerive.distinct()
|
||||
}
|
||||
|
||||
private fun getDefaultBlockchains(
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
): MutableList<BlockchainNetwork> {
|
||||
return mutableListOf(
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Bitcoin,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getEthereumBlockchains(derivationStyleProvider: DerivationStyleProvider): List<BlockchainNetwork> {
|
||||
return listOf(
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.Ethereum,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
BlockchainNetwork(
|
||||
blockchain = Blockchain.EthereumTestnet,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
private fun getAdditionalBlockchainToDerive(
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
collection: Collection<Blockchain>,
|
||||
): List<BlockchainNetwork> {
|
||||
return collection.map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
}
|
||||
return blockchainsToDerive.distinct()
|
||||
}
|
||||
|
||||
private fun getCardanoSecondNetwork(cardanoBlockchainNetwork: BlockchainNetwork): BlockchainNetwork? {
|
||||
val cardanoStandardDerivation = cardanoBlockchainNetwork.derivationPath?.let { DerivationPath(it) }
|
||||
?: return null
|
||||
val cardanoPatchedDerivation = CardanoUtils.extendedDerivationPath(cardanoStandardDerivation)
|
||||
return BlockchainNetwork(
|
||||
blockchain = Blockchain.Cardano,
|
||||
derivationPath = cardanoPatchedDerivation.rawPath,
|
||||
tokens = emptyList(),
|
||||
)
|
||||
}
|
||||
|
||||
private fun removeUnnecessaryBlockchains(
|
||||
blockchainsToDerive: MutableList<BlockchainNetwork>,
|
||||
derivationStyleProvider: DerivationStyleProvider,
|
||||
) {
|
||||
blockchainsToDerive.removeAll(
|
||||
listOf(
|
||||
Blockchain.BSC, Blockchain.BSCTestnet,
|
||||
Blockchain.Polygon, Blockchain.PolygonTestnet,
|
||||
Blockchain.RSK,
|
||||
Blockchain.Fantom, Blockchain.FantomTestnet,
|
||||
Blockchain.Avalanche, Blockchain.AvalancheTestnet,
|
||||
).map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
derivationStyleProvider = derivationStyleProvider,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun collectDerivations(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package com.tangem.tap.features.demo
|
|||
|
||||
import com.tangem.domain.demo.DemoConfig
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.extensions.dispatchNotification
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
|
|
@ -21,8 +22,8 @@ object DemoHelper {
|
|||
|
||||
private val disabledActionFeatures = listOf(
|
||||
WalletConnectAction.StartWalletConnect::class.java,
|
||||
WalletAction.TradeCryptoAction.Buy::class.java,
|
||||
WalletAction.TradeCryptoAction.Sell::class.java,
|
||||
TradeCryptoAction.Buy::class.java,
|
||||
TradeCryptoAction.Sell::class.java,
|
||||
BackupAction.StartBackup::class.java,
|
||||
WalletAction.ExploreAddress::class.java,
|
||||
DetailsAction.ResetToFactory.Start::class.java,
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import android.webkit.WebView
|
|||
import androidx.transition.TransitionInflater
|
||||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||
import com.tangem.core.ui.extensions.setStatusBarColor
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.tap.features.intentHandler.handlers
|
||||
|
||||
import android.content.Intent
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.extensions.dispatchWithMain
|
||||
import com.tangem.tap.features.intentHandler.IntentHandler
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.store
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ class SellCurrencyIntentHandler : IntentHandler {
|
|||
|
||||
Timber.d("MoonPay Sell: $amount $currency to $destinationAddress")
|
||||
store.dispatchWithMain(
|
||||
WalletAction.TradeCryptoAction.SendCrypto(
|
||||
TradeCryptoAction.SendCrypto(
|
||||
currencyId = currency,
|
||||
amount = amount,
|
||||
destinationAddress = destinationAddress,
|
||||
|
|
|
|||
|
|
@ -103,13 +103,16 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
tvBody.isVisible = false
|
||||
|
||||
btnMainAction.text = ""
|
||||
btnMainAction.icon = null
|
||||
btnAlternativeAction.text = ""
|
||||
btnAlternativeAction.icon = null
|
||||
tvHeader.text = ""
|
||||
tvBody.text = ""
|
||||
}
|
||||
|
||||
private fun setupCreateWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingNoteAction.CreateWallet)
|
||||
|
|
@ -133,6 +136,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
private fun setupTopUpWalletState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
|
||||
if (state.isBuyAllowed) {
|
||||
btnMainAction.setText(R.string.onboarding_top_up_button_but_crypto)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(OnboardingNoteAction.TopUp)
|
||||
}
|
||||
|
|
@ -144,6 +148,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
}
|
||||
} else {
|
||||
btnMainAction.setText(R.string.onboarding_button_receive_crypto)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(OnboardingNoteAction.ShowAddressInfoDialog)
|
||||
}
|
||||
|
|
@ -179,6 +184,7 @@ class OnboardingNoteFragment : BaseOnboardingFragment<OnboardingNoteState>() {
|
|||
|
||||
private fun setupDoneState(state: OnboardingNoteState) = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.common_continue)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
showConfetti(false)
|
||||
store.dispatch(OnboardingNoteAction.Done)
|
||||
|
|
|
|||
|
|
@ -72,6 +72,7 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
|
||||
private fun setupCreateWalletState() = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingOtherCardsAction.CreateWallet)
|
||||
|
|
@ -92,6 +93,7 @@ class OnboardingOtherCardsFragment : BaseOnboardingFragment<OnboardingOtherCards
|
|||
|
||||
private fun setupDoneState() = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.common_continue)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
showConfetti(false)
|
||||
store.dispatch(OnboardingOtherCardsAction.Done)
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import android.util.TypedValue
|
|||
import android.view.View
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import androidx.annotation.LayoutRes
|
||||
import androidx.appcompat.content.res.AppCompatResources
|
||||
import androidx.constraintlayout.widget.ConstraintSet
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionInflater
|
||||
|
|
@ -15,7 +16,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.ShareElement
|
||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||
import com.tangem.core.ui.extensions.setStatusBarColor
|
||||
import com.tangem.datasource.asset.AssetReader
|
||||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
|
|
@ -175,10 +176,12 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
}
|
||||
|
||||
private fun setupWelcomeState(state: TwinCardsState) {
|
||||
setupWelcomeState(state) { store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.CreateFirstWallet)) }
|
||||
setupWelcomeState(state) {
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.CreateFirstWallet))
|
||||
}
|
||||
}
|
||||
|
||||
private fun setupWelcomeState(state: TwinCardsState, mainAction: VoidCallback) =
|
||||
private fun setupWelcomeState(state: TwinCardsState, onMainButtonClick: VoidCallback) =
|
||||
with(mainBinding.onboardingActionContainer) {
|
||||
twinsWidget.toWelcome(false)
|
||||
|
||||
|
|
@ -192,7 +195,12 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
)
|
||||
|
||||
btnMainAction.setText(R.string.common_continue)
|
||||
btnMainAction.setOnClickListener { mainAction() }
|
||||
btnMainAction.icon = when (state.currentStep) {
|
||||
is TwinCardsStep.WelcomeOnly -> null
|
||||
is TwinCardsStep.Welcome -> AppCompatResources.getDrawable(requireContext(), R.drawable.ic_tangem_24)
|
||||
else -> null
|
||||
}
|
||||
btnMainAction.setOnClickListener { onMainButtonClick() }
|
||||
}
|
||||
|
||||
private fun setupWarningState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
|
||||
|
|
@ -210,6 +218,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
}
|
||||
btnMainAction.isEnabled = state.userWasUnderstandIfWalletRecreate
|
||||
btnMainAction.setText(R.string.common_continue)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.SetStepOfScreen(TwinCardsStep.CreateFirstWallet))
|
||||
}
|
||||
|
|
@ -251,6 +260,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
tvBody.setText(R.string.onboarding_twins_interrupt_warning)
|
||||
|
||||
btnMainAction.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
|
||||
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(
|
||||
|
|
@ -274,6 +284,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
|
||||
btnMainAction.text =
|
||||
getString(R.string.twins_recreate_button_format, twinPairIndexNumber)
|
||||
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(
|
||||
TwinCardsAction.Wallet.LaunchSecondStep(
|
||||
|
|
@ -298,6 +309,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
tvBody.setText(R.string.onboarding_twins_interrupt_warning)
|
||||
|
||||
btnMainAction.text = getString(R.string.twins_recreate_button_format, twinIndexNumber)
|
||||
btnMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(
|
||||
TwinCardsAction.Wallet.LaunchThirdStep(
|
||||
|
|
@ -343,6 +355,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
}
|
||||
} else {
|
||||
btnMainAction.setText(R.string.onboarding_button_receive_crypto)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.ShowAddressInfoDialog)
|
||||
}
|
||||
|
|
@ -367,6 +380,7 @@ class TwinsCardsFragment : BaseOnboardingFragment<TwinCardsState>() {
|
|||
|
||||
private fun setupDoneState(state: TwinCardsState) = with(mainBinding.onboardingActionContainer) {
|
||||
btnMainAction.setText(R.string.common_continue)
|
||||
btnMainAction.icon = null
|
||||
btnMainAction.setOnClickListener {
|
||||
store.dispatch(TwinCardsAction.Confetti.Hide)
|
||||
store.dispatch(TwinCardsAction.Done)
|
||||
|
|
|
|||
|
|
@ -204,6 +204,8 @@ class OnboardingWalletFragment :
|
|||
|
||||
private fun setupCreateWalletState() = with(binding) {
|
||||
layoutButtonsCommon.btnWalletMainAction.setText(R.string.onboarding_create_wallet_button_create_wallet)
|
||||
layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener {
|
||||
Analytics.send(Onboarding.CreateWallet.ButtonCreateWallet())
|
||||
store.dispatch(OnboardingWalletAction.CreateWallet)
|
||||
|
|
@ -243,6 +245,7 @@ class OnboardingWalletFragment :
|
|||
|
||||
with(layoutButtonsCommon) {
|
||||
btnWalletMainAction.text = getText(R.string.onboarding_button_backup_now)
|
||||
btnWalletMainAction.icon = null
|
||||
btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.StartBackup) }
|
||||
|
||||
btnWalletAlternativeAction.text = getText(R.string.onboarding_button_skip_backup)
|
||||
|
|
@ -261,6 +264,7 @@ class OnboardingWalletFragment :
|
|||
|
||||
with(layoutButtonsCommon) {
|
||||
btnWalletMainAction.text = getString(R.string.onboarding_button_scan_origin_card)
|
||||
btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
btnWalletAlternativeAction.hide()
|
||||
btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.ScanPrimaryCard) }
|
||||
}
|
||||
|
|
@ -277,6 +281,7 @@ class OnboardingWalletFragment :
|
|||
layoutButtonsAddCards.root.show()
|
||||
layoutButtonsCommon.root.hide()
|
||||
layoutButtonsAddCards.btnAddCard.text = getText(R.string.onboarding_button_add_backup_card)
|
||||
layoutButtonsAddCards.btnAddCard.setIconResource(R.drawable.ic_tangem_24)
|
||||
if (state.backupCardsNumber < state.maxBackupCards) {
|
||||
layoutButtonsAddCards.btnAddCard.setOnClickListener { store.dispatch(BackupAction.AddBackupCard) }
|
||||
} else {
|
||||
|
|
@ -358,6 +363,7 @@ class OnboardingWalletFragment :
|
|||
state.primaryCardId?.let { cardIdFormatter.getFormattedCardId(it) },
|
||||
)
|
||||
layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_backup_origin)
|
||||
layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener { store.dispatch(BackupAction.WritePrimaryCard) }
|
||||
|
||||
animator.showWritePrimaryCard(state)
|
||||
|
|
@ -390,6 +396,7 @@ class OnboardingWalletFragment :
|
|||
R.string.onboarding_button_backup_card_format,
|
||||
cardNumber,
|
||||
)
|
||||
layoutButtonsCommon.btnWalletMainAction.setIconResource(R.drawable.ic_tangem_24)
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener {
|
||||
store.dispatch(BackupAction.WriteBackupCard(cardNumber))
|
||||
}
|
||||
|
|
@ -408,6 +415,7 @@ class OnboardingWalletFragment :
|
|||
|
||||
tvBody.text = getText(R.string.onboarding_subtitle_success_tangem_wallet_onboarding)
|
||||
layoutButtonsCommon.btnWalletMainAction.text = getText(R.string.onboarding_button_continue_wallet)
|
||||
layoutButtonsCommon.btnWalletMainAction.icon = null
|
||||
layoutButtonsCommon.btnWalletAlternativeAction.hide()
|
||||
layoutButtonsCommon.btnWalletMainAction.setOnClickListener {
|
||||
showConfetti(false)
|
||||
|
|
|
|||
|
|
@ -6,24 +6,27 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.fragment.app.viewModels
|
||||
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeBottomSheetFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
||||
import com.tangem.tap.features.saveWallet.ui.components.EnrollBiometricsDialogContent
|
||||
import com.tangem.tap.features.saveWallet.ui.components.SaveWalletScreenContent
|
||||
import com.tangem.tap.features.saveWallet.ui.models.EnrollBiometricsDialog
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment() {
|
||||
|
||||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment<SaveWalletScreenState>() {
|
||||
override val expandedHeightFraction: Float = .98f
|
||||
|
||||
private val viewModel by viewModels<SaveWalletViewModel>()
|
||||
|
|
@ -34,12 +37,8 @@ internal class SaveWalletBottomSheetFragment : ComposeBottomSheetFragment<SaveWa
|
|||
}
|
||||
|
||||
@Composable
|
||||
override fun provideState(): State<SaveWalletScreenState> {
|
||||
return viewModel.state.collectAsState()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(state: SaveWalletScreenState, modifier: Modifier) {
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference())
|
||||
val enrollBiometricsDialog by rememberUpdatedState(newValue = state.enrollBiometricsDialog)
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
|||
import com.tangem.domain.common.extensions.minimalAmount
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.*
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
|
|
@ -38,7 +39,6 @@ import com.tangem.tap.features.send.redux.*
|
|||
import com.tangem.tap.features.send.redux.FeeAction.RequestFee
|
||||
import com.tangem.tap.features.send.redux.states.*
|
||||
import com.tangem.tap.features.wallet.models.Currency
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.wallet.R
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -254,7 +254,7 @@ private fun sendTransaction(
|
|||
),
|
||||
)
|
||||
Analytics.sendSelectedCurrencyEvent(mainCurrencyType)
|
||||
dispatch(WalletAction.TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
|
||||
dispatch(TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
|
||||
} else {
|
||||
Analytics.send(
|
||||
Basic.TransactionSent(
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.google.android.material.textfield.TextInputEditText
|
|||
import com.tangem.Message
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.sdk.extensions.hideSoftKeyboard
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
|
|
@ -39,7 +40,6 @@ import com.tangem.tap.features.send.redux.FeeActionUi.*
|
|||
import com.tangem.tap.features.send.redux.states.FeeType
|
||||
import com.tangem.tap.features.send.redux.states.MainCurrencyType
|
||||
import com.tangem.tap.features.send.ui.stateSubscribers.SendStateSubscriber
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.ui.adapters.WarningMessagesAdapter
|
||||
import com.tangem.tap.mainScope
|
||||
import com.tangem.tap.store
|
||||
|
|
@ -337,9 +337,7 @@ class SendFragment : BaseStoreFragment(R.layout.fragment_send) {
|
|||
if (externalTransactionData == null) {
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
} else {
|
||||
store.dispatch(
|
||||
WalletAction.TradeCryptoAction.FinishSelling(externalTransactionData.transactionId),
|
||||
)
|
||||
store.dispatch(TradeCryptoAction.FinishSelling(externalTransactionData.transactionId))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,24 @@ import androidx.activity.viewModels
|
|||
import androidx.compose.foundation.layout.imePadding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.ui.fragments.ComposeActivity
|
||||
import com.tangem.core.ui.components.SystemBarsEffect
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeActivity
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.tap.common.analytics.events.Chat
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class SprinklrActivity : ComposeActivity() {
|
||||
|
||||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
internal class SprinklrActivity : ComposeActivity<SprinklrScreenState>() {
|
||||
private val viewModel by viewModels<SprinklrViewModel>()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
@ -25,12 +35,14 @@ internal class SprinklrActivity : ComposeActivity<SprinklrScreenState>() {
|
|||
}
|
||||
|
||||
@Composable
|
||||
override fun provideState(): State<SprinklrScreenState> {
|
||||
return viewModel.state.collectAsState()
|
||||
}
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
|
||||
val systemBarsColor = TangemTheme.colors.background.primary
|
||||
SystemBarsEffect {
|
||||
setSystemBarsColor(systemBarsColor)
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(state: SprinklrScreenState, modifier: Modifier) {
|
||||
BackHandler(onBack = state.onNavigateBack)
|
||||
SprinklrScreenContent(
|
||||
modifier = modifier
|
||||
|
|
|
|||
|
|
@ -7,17 +7,14 @@ import androidx.compose.animation.fadeOut
|
|||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.CircularProgressIndicator
|
||||
import androidx.compose.material.FabPosition
|
||||
import androidx.compose.material.Scaffold
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
import androidx.compose.ui.Modifier
|
||||
|
|
@ -32,9 +29,7 @@ import androidx.compose.ui.unit.TextUnit
|
|||
import androidx.compose.ui.unit.TextUnitType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import androidx.paging.compose.items
|
||||
import androidx.paging.compose.*
|
||||
import com.tangem.core.ui.components.PrimaryButton
|
||||
import com.tangem.core.ui.res.TangemColorPalette
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
|
|
@ -134,8 +129,11 @@ private fun TokensListContent(
|
|||
item { DifferentAddressesWarning() }
|
||||
}
|
||||
|
||||
items(items = tokens, key = TokenItemState::composedId) {
|
||||
it?.let { TokenItem(model = it) }
|
||||
tokens.itemKey(TokenItemState::composedId)
|
||||
tokens.itemContentType(TokenItemState::composedId)
|
||||
|
||||
items(items = tokens.itemSnapshotList.items, key = TokenItemState::composedId) {
|
||||
TokenItem(model = it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.tap.features.wallet.models.Currency
|
|||
import com.tangem.tap.store
|
||||
import com.tangem.utils.converter.Converter
|
||||
|
||||
class CryptoCurrencyConverter : Converter<Currency, CryptoCurrency> {
|
||||
internal class CryptoCurrencyConverter : Converter<Currency, CryptoCurrency> {
|
||||
|
||||
private val cryptoCurrencyFactory by lazy { CryptoCurrencyFactory() }
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,16 @@ import androidx.core.os.bundleOf
|
|||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.common.extensions.toCoinId
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.tokens.models.CryptoCurrency
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
|
|
@ -27,6 +31,7 @@ import com.tangem.tap.features.wallet.redux.WalletAction
|
|||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import com.tangem.tap.network.exchangeServices.CurrencyExchangeManager
|
||||
import com.tangem.tap.network.exchangeServices.buyErc20TestnetTokens
|
||||
import com.tangem.tap.proxy.redux.DaggerGraphState
|
||||
import com.tangem.tap.scope
|
||||
import com.tangem.tap.store
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -35,19 +40,27 @@ import kotlinx.serialization.json.Json
|
|||
import com.tangem.feature.swap.domain.models.domain.Currency as SwapCurrency
|
||||
|
||||
class TradeCryptoMiddleware {
|
||||
fun handle(state: () -> AppState?, action: WalletAction.TradeCryptoAction) {
|
||||
fun handle(state: () -> AppState?, action: TradeCryptoAction) {
|
||||
if (DemoHelper.tryHandle(state, action)) return
|
||||
|
||||
when (action) {
|
||||
is WalletAction.TradeCryptoAction.Buy -> proceedBuyAction(state, action)
|
||||
is WalletAction.TradeCryptoAction.Sell -> proceedSellAction()
|
||||
is WalletAction.TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action)
|
||||
is WalletAction.TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
|
||||
is WalletAction.TradeCryptoAction.Swap -> openSwap()
|
||||
is TradeCryptoAction.Buy -> proceedBuyAction(state, action)
|
||||
is TradeCryptoAction.Sell -> proceedSellAction()
|
||||
is TradeCryptoAction.SendCrypto -> preconfigureAndOpenSendScreen(action)
|
||||
is TradeCryptoAction.FinishSelling -> openReceiptUrl(action.transactionId)
|
||||
is TradeCryptoAction.Swap -> {
|
||||
openSwap(currency = store.state.walletState.selectedWalletData?.currency?.toSwapCurrency())
|
||||
}
|
||||
is TradeCryptoAction.New.Buy -> proceedNewBuyAction(state, action)
|
||||
TradeCryptoAction.New.Send -> store.dispatch(WalletAction.Send())
|
||||
is TradeCryptoAction.New.Sell -> proceedNewSellAction(action)
|
||||
is TradeCryptoAction.New.Swap -> {
|
||||
openSwap(currency = action.cryptoCurrency.toSwapCurrency())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedBuyAction(state: () -> AppState?, action: WalletAction.TradeCryptoAction.Buy) {
|
||||
private fun proceedBuyAction(state: () -> AppState?, action: TradeCryptoAction.Buy) {
|
||||
val selectedWalletData = store.state.walletState.selectedWalletData ?: return
|
||||
val currency = chooseAppropriateCurrency(store.state.walletState) ?: return
|
||||
|
||||
|
|
@ -75,7 +88,7 @@ class TradeCryptoMiddleware {
|
|||
buyErc20TestnetTokens(
|
||||
card = card,
|
||||
walletManager = walletManager,
|
||||
token = currency.token,
|
||||
destinationAddress = currency.token.contractAddress,
|
||||
)
|
||||
}
|
||||
return
|
||||
|
|
@ -93,6 +106,56 @@ class TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedNewBuyAction(state: () -> AppState?, action: TradeCryptoAction.New.Buy) {
|
||||
val networkAddress = action.cryptoCurrencyStatus.value.networkAddress?.defaultAddress ?: return
|
||||
|
||||
if (action.checkUserLocation && state()?.globalState?.userCountryCode == RUSSIA_COUNTRY_CODE) {
|
||||
store.dispatchOnMain(WalletAction.DialogAction.RussianCardholdersWarningDialog())
|
||||
return
|
||||
}
|
||||
|
||||
val status = action.cryptoCurrencyStatus
|
||||
val currency = status.currency
|
||||
val blockchain = Blockchain.fromId(currency.network.id.value)
|
||||
if (currency is CryptoCurrency.Token && currency.network.isTestnet) {
|
||||
scope.launch {
|
||||
val walletManager = store.state.daggerGraphState
|
||||
.get(DaggerGraphState::walletManagersFacade)
|
||||
.getOrCreateWalletManager(
|
||||
userWallet = action.userWallet,
|
||||
blockchain = blockchain,
|
||||
derivationPath = blockchain.derivationPath(
|
||||
style = action.userWallet.scanResponse.derivationStyleProvider.getDerivationStyle(),
|
||||
),
|
||||
)
|
||||
|
||||
if (walletManager !is EthereumWalletManager) {
|
||||
store.dispatchDebugErrorNotification("Testnet tokens available only for the Ethereum")
|
||||
return@launch
|
||||
}
|
||||
|
||||
buyErc20TestnetTokens(
|
||||
card = action.userWallet.scanResponse.card,
|
||||
walletManager = walletManager,
|
||||
destinationAddress = currency.contractAddress,
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
exchangeManager.getUrl(
|
||||
action = CurrencyExchangeManager.Action.Buy,
|
||||
blockchain = blockchain,
|
||||
cryptoCurrencyName = currency.symbol,
|
||||
fiatCurrencyName = action.appCurrencyCode,
|
||||
walletAddress = networkAddress,
|
||||
)?.let {
|
||||
store.dispatchOpenUrl(it)
|
||||
Analytics.send(Token.Topup.ScreenOpened())
|
||||
}
|
||||
}
|
||||
|
||||
private fun proceedSellAction() {
|
||||
val selectedWalletData = store.state.walletState.selectedWalletData ?: return
|
||||
val currency = chooseAppropriateCurrency(store.state.walletState) ?: return
|
||||
|
|
@ -115,6 +178,22 @@ class TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun proceedNewSellAction(action: TradeCryptoAction.New.Sell) {
|
||||
val networkAddress = action.cryptoCurrencyStatus.value.networkAddress?.defaultAddress ?: return
|
||||
val currency = action.cryptoCurrencyStatus.currency
|
||||
|
||||
store.state.globalState.exchangeManager.getUrl(
|
||||
action = CurrencyExchangeManager.Action.Sell,
|
||||
blockchain = Blockchain.fromId(currency.network.id.value),
|
||||
cryptoCurrencyName = currency.symbol,
|
||||
fiatCurrencyName = action.appCurrencyCode,
|
||||
walletAddress = networkAddress,
|
||||
)?.let {
|
||||
store.dispatchOpenUrl(it)
|
||||
Analytics.send(Token.Withdraw.ScreenOpened())
|
||||
}
|
||||
}
|
||||
|
||||
private fun chooseAppropriateCurrency(walletState: WalletState): Currency? {
|
||||
return if (walletState.primaryTokenData == null) {
|
||||
walletState.selectedWalletData?.currency
|
||||
|
|
@ -126,7 +205,7 @@ class TradeCryptoMiddleware {
|
|||
}
|
||||
}
|
||||
|
||||
private fun preconfigureAndOpenSendScreen(action: WalletAction.TradeCryptoAction.SendCrypto) {
|
||||
private fun preconfigureAndOpenSendScreen(action: TradeCryptoAction.SendCrypto) {
|
||||
val selectedWalletData = store.state.walletState.selectedWalletData ?: return
|
||||
|
||||
Analytics.send(Token.ButtonSend(AnalyticsParam.CurrencyType.Currency(selectedWalletData.currency)))
|
||||
|
|
@ -160,16 +239,44 @@ class TradeCryptoMiddleware {
|
|||
)?.let { store.dispatchOpenUrl(it) }
|
||||
}
|
||||
|
||||
private fun openSwap() {
|
||||
val currency = store.state.walletState.selectedWalletData?.currency?.toSwapCurrency()
|
||||
val bundle =
|
||||
bundleOf(
|
||||
SwapFragment.CURRENCY_BUNDLE_KEY to Json.encodeToString(currency),
|
||||
SwapFragment.DERIVATION_PATH to store.state.walletState.selectedWalletData?.currency?.derivationPath,
|
||||
)
|
||||
private fun openSwap(currency: SwapCurrency?) {
|
||||
val bundle = bundleOf(
|
||||
SwapFragment.CURRENCY_BUNDLE_KEY to Json.encodeToString(currency),
|
||||
SwapFragment.DERIVATION_PATH to store.state.walletState.selectedWalletData?.currency?.derivationPath,
|
||||
)
|
||||
|
||||
store.dispatchOnMain(NavigationAction.NavigateTo(screen = AppScreen.Swap, bundle = bundle))
|
||||
}
|
||||
|
||||
private fun CryptoCurrency.toSwapCurrency(): SwapCurrency {
|
||||
val blockchain = Blockchain.fromId(network.id.value)
|
||||
|
||||
return when (this) {
|
||||
is CryptoCurrency.Coin -> {
|
||||
SwapCurrency.NativeToken(
|
||||
id = blockchain.toCoinId(),
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
networkId = blockchain.toNetworkId(),
|
||||
// no need to set logoUrl for blockchain cause
|
||||
// error when form url with coinId, coinId of eth and arbitrum the same
|
||||
logoUrl = "",
|
||||
)
|
||||
}
|
||||
is CryptoCurrency.Token -> {
|
||||
SwapCurrency.NonNativeToken(
|
||||
id = id.value,
|
||||
name = name,
|
||||
symbol = symbol,
|
||||
networkId = blockchain.toNetworkId(),
|
||||
logoUrl = getIconUrl(id.value),
|
||||
contractAddress = contractAddress,
|
||||
decimalCount = decimals,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Currency.toSwapCurrency(): SwapCurrency {
|
||||
return when (this) {
|
||||
is Currency.Blockchain -> {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.domain.userwallets.GetCardImageUseCase
|
||||
import com.tangem.domain.wallets.legacy.lockIfLockable
|
||||
import com.tangem.tap.*
|
||||
|
|
@ -87,7 +88,7 @@ class WalletMiddleware {
|
|||
val walletState = store.state.walletState
|
||||
|
||||
when (action) {
|
||||
is WalletAction.TradeCryptoAction -> tradeCryptoMiddleware.handle(state, action)
|
||||
is TradeCryptoAction -> tradeCryptoMiddleware.handle(state, action)
|
||||
is WalletAction.Warnings -> warningsMiddleware.handle(action, globalState)
|
||||
is WalletAction.MultiWallet -> multiWalletMiddleware.handle(action, walletState)
|
||||
is WalletAction.AppCurrencyAction -> appCurrencyMiddleware.handle(action)
|
||||
|
|
|
|||
|
|
@ -68,7 +68,6 @@ private fun internalReduce(action: Action, state: AppState, appStateHolder: AppS
|
|||
error = null,
|
||||
)
|
||||
}
|
||||
is WalletAction.TradeCryptoAction -> return newState
|
||||
is WalletAction.AppCurrencyAction -> {
|
||||
newState = appCurrencyReducer.reduce(action, newState)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import com.tangem.core.analytics.Analytics
|
|||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.domain.common.util.derivationStyleProvider
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.feature.swap.api.SwapFeatureToggleManager
|
||||
import com.tangem.feature.swap.domain.SwapInteractor
|
||||
import com.tangem.sdk.extensions.dpToPx
|
||||
|
|
@ -276,9 +277,9 @@ class WalletDetailsFragment : Fragment(R.layout.fragment_wallet_details), SafeSt
|
|||
) {
|
||||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
binding.rowButtons.apply {
|
||||
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
|
||||
onSellClick = { store.dispatch(WalletAction.TradeCryptoAction.Sell) }
|
||||
onSwapClick = { store.dispatch(WalletAction.TradeCryptoAction.Swap) }
|
||||
onBuyClick = { store.dispatch(TradeCryptoAction.Buy()) }
|
||||
onSellClick = { store.dispatch(TradeCryptoAction.Sell) }
|
||||
onSwapClick = { store.dispatch(TradeCryptoAction.Swap) }
|
||||
onTradeClick = {
|
||||
store.dispatch(
|
||||
WalletAction.DialogAction.ChooseTradeActionDialog(
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ import com.badoo.mvicore.modelWatcher
|
|||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.AppScreen
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||
import com.tangem.core.ui.extensions.setStatusBarColor
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.utils.OneTouchClickListener
|
||||
import com.tangem.datasource.connection.NetworkConnectionManager
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.content.Context
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
|
|
@ -39,15 +40,15 @@ class ChooseTradeActionBottomSheetDialog(
|
|||
|
||||
dialogBtnBuy.setOnClickListener {
|
||||
dismiss()
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Buy())
|
||||
store.dispatch(TradeCryptoAction.Buy())
|
||||
}
|
||||
dialogBtnSell.setOnClickListener {
|
||||
dismiss()
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Sell)
|
||||
store.dispatch(TradeCryptoAction.Sell)
|
||||
}
|
||||
dialogBtnSwap.setOnClickListener {
|
||||
dismiss()
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Swap)
|
||||
store.dispatch(TradeCryptoAction.Swap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ import android.view.LayoutInflater
|
|||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.navigation.NavigationAction
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.extensions.dispatchOpenUrl
|
||||
import com.tangem.tap.features.wallet.redux.WalletAction
|
||||
import com.tangem.tap.features.wallet.redux.models.WalletDialog
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.databinding.DialogRussiansCardholdersWarningBinding
|
||||
|
|
@ -40,7 +40,7 @@ class RussianCardholdersWarningBottomSheetDialog(
|
|||
if (dialogData != null) {
|
||||
store.dispatchOpenUrl(dialogData.topUpUrl)
|
||||
} else {
|
||||
store.dispatch(WalletAction.TradeCryptoAction.Buy(checkUserLocation = false))
|
||||
store.dispatch(TradeCryptoAction.Buy(checkUserLocation = false))
|
||||
}
|
||||
dismiss()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import android.view.View
|
|||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.tokens.legacy.TradeCryptoAction
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.*
|
||||
import com.tangem.tap.domain.model.WalletDataModel
|
||||
|
|
@ -151,9 +152,9 @@ class SingleWalletView : WalletView() {
|
|||
|
||||
val exchangeManager = store.state.globalState.exchangeManager
|
||||
binding?.rowButtons?.apply {
|
||||
onBuyClick = { store.dispatch(WalletAction.TradeCryptoAction.Buy()) }
|
||||
onSellClick = { store.dispatch(WalletAction.TradeCryptoAction.Sell) }
|
||||
onSwapClick = { store.dispatch(WalletAction.TradeCryptoAction.Swap) }
|
||||
onBuyClick = { store.dispatch(TradeCryptoAction.Buy()) }
|
||||
onSellClick = { store.dispatch(TradeCryptoAction.Sell) }
|
||||
onSwapClick = { store.dispatch(TradeCryptoAction.Swap) }
|
||||
onTradeClick = {
|
||||
store.dispatch(
|
||||
WalletAction.DialogAction.ChooseTradeActionDialog(
|
||||
|
|
|
|||
|
|
@ -7,35 +7,32 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
||||
import com.tangem.core.ui.components.wallets.RenameWalletDialogContent
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeBottomSheetFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.tap.common.analytics.events.MyWallets
|
||||
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
||||
import com.tangem.tap.features.walletSelector.ui.components.BiometricsDisabledWarningContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.BiometricsLockoutWarningContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.KeyInvalidatedWarningContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.RemoveWalletDialogContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.RenameWalletDialogContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.WalletSelectorScreenContent
|
||||
import com.tangem.tap.features.walletSelector.ui.components.*
|
||||
import com.tangem.tap.features.walletSelector.ui.model.DialogModel
|
||||
import com.tangem.tap.features.walletSelector.ui.model.WarningModel
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
@AndroidEntryPoint
|
||||
internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<WalletSelectorScreenState>() {
|
||||
internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment() {
|
||||
|
||||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
private val viewModel by viewModels<WalletSelectorViewModel>()
|
||||
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
|
@ -45,10 +42,8 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
|
|||
}
|
||||
|
||||
@Composable
|
||||
override fun provideState(): State<WalletSelectorScreenState> = viewModel.state.collectAsState()
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(state: WalletSelectorScreenState, modifier: Modifier) {
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference())
|
||||
val dialog by rememberUpdatedState(newValue = state.dialog)
|
||||
|
|
@ -90,7 +85,13 @@ internal class WalletSelectorBottomSheetFragment : ComposeBottomSheetFragment<Wa
|
|||
if (dialog == null) return
|
||||
when (dialog) {
|
||||
is DialogModel.RemoveWalletDialog -> RemoveWalletDialogContent(dialog)
|
||||
is DialogModel.RenameWalletDialog -> RenameWalletDialogContent(dialog)
|
||||
is DialogModel.RenameWalletDialog -> {
|
||||
RenameWalletDialogContent(
|
||||
name = dialog.currentName,
|
||||
onConfirm = dialog.onConfirm,
|
||||
onDismiss = dialog.onDismiss,
|
||||
)
|
||||
}
|
||||
is WarningModel.BiometricsLockoutWarning -> BiometricsLockoutWarningContent(dialog)
|
||||
is WarningModel.KeyInvalidatedWarning -> KeyInvalidatedWarningContent(dialog)
|
||||
is WarningModel.BiometricsDisabledWarning -> BiometricsDisabledWarningContent(dialog)
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
package com.tangem.tap.features.walletSelector.ui.components
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.input.TextFieldValue
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.tangem.core.ui.components.AdditionalTextInputDialogParams
|
||||
import com.tangem.core.ui.components.DialogButton
|
||||
import com.tangem.core.ui.components.TextInputDialog
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.features.walletSelector.ui.model.DialogModel
|
||||
import com.tangem.wallet.R
|
||||
|
||||
@Composable
|
||||
internal fun RenameWalletDialogContent(dialog: DialogModel.RenameWalletDialog) {
|
||||
var value by remember {
|
||||
mutableStateOf(TextFieldValue(text = dialog.currentName))
|
||||
}
|
||||
|
||||
TextInputDialog(
|
||||
fieldValue = value,
|
||||
confirmButton = DialogButton(
|
||||
title = stringResource(id = R.string.common_ok),
|
||||
enabled = value.text.isNotEmpty() && value.text != dialog.currentName,
|
||||
onClick = { dialog.onConfirm(value.text) },
|
||||
),
|
||||
onDismissDialog = dialog.onDismiss,
|
||||
onValueChange = { newValue ->
|
||||
value = newValue
|
||||
},
|
||||
title = stringResource(R.string.user_wallet_list_rename_popup_title),
|
||||
dismissButton = DialogButton(
|
||||
title = stringResource(id = R.string.common_cancel),
|
||||
onClick = dialog.onDismiss,
|
||||
),
|
||||
textFieldParams = AdditionalTextInputDialogParams(
|
||||
label = stringResource(R.string.user_wallet_list_rename_popup_placeholder),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// region Preview
|
||||
@Composable
|
||||
private fun RenameWalletDialogContentSample(modifier: Modifier = Modifier) {
|
||||
Column(
|
||||
modifier = modifier,
|
||||
) {
|
||||
RenameWalletDialogContent(dialog = DialogModel.RenameWalletDialog("", {}, {}))
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Composable
|
||||
private fun RenameWalletDialogContentPreview_Light() {
|
||||
TangemTheme {
|
||||
RenameWalletDialogContentSample()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview(showBackground = true, widthDp = 360)
|
||||
@Composable
|
||||
private fun RenameWalletDialogContentPreview_Dark() {
|
||||
TangemTheme(isDark = true) {
|
||||
RenameWalletDialogContentSample()
|
||||
}
|
||||
}
|
||||
// endregion Preview
|
||||
|
|
@ -1,35 +1,36 @@
|
|||
package com.tangem.tap.features.welcome.ui
|
||||
|
||||
import androidx.activity.compose.BackHandler
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.systemBarsPadding
|
||||
import androidx.compose.material.SnackbarHost
|
||||
import androidx.compose.material.SnackbarHostState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.colorResource
|
||||
import androidx.fragment.app.viewModels
|
||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.ui.components.SystemBarsEffect
|
||||
import com.tangem.core.ui.fragments.ComposeFragment
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.core.ui.screen.ComposeFragment
|
||||
import com.tangem.core.ui.theme.AppThemeModeHolder
|
||||
import com.tangem.tap.common.analytics.events.SignIn
|
||||
import com.tangem.tap.common.extensions.eraseContext
|
||||
import com.tangem.tap.features.details.ui.cardsettings.resolveReference
|
||||
import com.tangem.tap.features.welcome.ui.components.WarningDialog
|
||||
import com.tangem.tap.features.welcome.ui.components.WelcomeScreenContent
|
||||
import com.tangem.wallet.R
|
||||
import dagger.hilt.android.AndroidEntryPoint
|
||||
import javax.inject.Inject
|
||||
|
||||
internal class WelcomeFragment : ComposeFragment<WelcomeScreenState>() {
|
||||
@AndroidEntryPoint
|
||||
internal class WelcomeFragment : ComposeFragment() {
|
||||
|
||||
@Inject
|
||||
override lateinit var appThemeModeHolder: AppThemeModeHolder
|
||||
|
||||
private val viewModel by viewModels<WelcomeViewModel>()
|
||||
|
||||
|
|
@ -40,19 +41,15 @@ internal class WelcomeFragment : ComposeFragment<WelcomeScreenState>() {
|
|||
}
|
||||
|
||||
@Composable
|
||||
override fun provideState(): State<WelcomeScreenState> {
|
||||
return viewModel.state.collectAsState()
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun ScreenContent(state: WelcomeScreenState, modifier: Modifier) {
|
||||
override fun ScreenContent(modifier: Modifier) {
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val snackbarHostState = remember { SnackbarHostState() }
|
||||
val errorMessage by rememberUpdatedState(newValue = state.error?.resolveReference())
|
||||
val warning by rememberUpdatedState(newValue = state.warning)
|
||||
|
||||
val backgroundColor = colorResource(id = R.color.background_primary)
|
||||
val backgroundColor = TangemTheme.colors.background.primary
|
||||
SystemBarsEffect {
|
||||
setSystemBarsColor(color = backgroundColor)
|
||||
setSystemBarsColor(backgroundColor)
|
||||
}
|
||||
|
||||
BackHandler {
|
||||
|
|
@ -61,7 +58,8 @@ internal class WelcomeFragment : ComposeFragment<WelcomeScreenState>() {
|
|||
|
||||
Box(
|
||||
modifier = modifier
|
||||
.systemBarsPadding(),
|
||||
.systemBarsPadding()
|
||||
.background(backgroundColor),
|
||||
) {
|
||||
WelcomeScreenContent(
|
||||
showUnlockProgress = state.showUnlockWithBiometricsProgress,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
|||
import com.tangem.blockchain.common.Amount
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.blockchain.common.Token
|
||||
import com.tangem.blockchain.common.transaction.TransactionFee
|
||||
import com.tangem.blockchain.extensions.Result
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
|
|
@ -87,17 +86,12 @@ class CurrencyExchangeManager(
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, token: Token) {
|
||||
suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletManager, destinationAddress: String) {
|
||||
walletManager.safeUpdate()
|
||||
|
||||
val amountToSend = Amount(walletManager.wallet.blockchain)
|
||||
val destinationAddress = token.contractAddress
|
||||
|
||||
val feeResult = walletManager.getFee(
|
||||
amountToSend,
|
||||
destinationAddress,
|
||||
) as? Result.Success ?: return
|
||||
|
||||
val feeResult = walletManager.getFee(amountToSend, destinationAddress) as? Result.Success ?: return
|
||||
val fee = when (val feeForTx = feeResult.data) {
|
||||
is TransactionFee.Choosable -> feeForTx.minimum
|
||||
is TransactionFee.Single -> feeForTx.normal
|
||||
|
|
@ -106,8 +100,6 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa
|
|||
val coinValue = walletManager.wallet.amounts[AmountType.Coin]?.value ?: BigDecimal.ZERO
|
||||
if (coinValue < fee.amount.value) return
|
||||
|
||||
val transaction = walletManager.createTransaction(amountToSend, fee, destinationAddress)
|
||||
|
||||
val signer = TangemSigner(
|
||||
card = card,
|
||||
tangemSdk = store.state.daggerGraphState.get(DaggerGraphState::cardSdkConfigRepository).sdk,
|
||||
|
|
@ -121,5 +113,13 @@ suspend fun buyErc20TestnetTokens(card: CardDTO, walletManager: EthereumWalletMa
|
|||
),
|
||||
)
|
||||
}
|
||||
walletManager.send(transaction, signer)
|
||||
|
||||
walletManager.send(
|
||||
transactionData = walletManager.createTransaction(
|
||||
amount = amountToSend,
|
||||
fee = fee,
|
||||
destination = destinationAddress,
|
||||
),
|
||||
signer = signer,
|
||||
)
|
||||
}
|
||||
|
|
@ -4,6 +4,7 @@ import com.tangem.core.navigation.NavigationAction
|
|||
import com.tangem.core.navigation.NavigationStateHolder
|
||||
import com.tangem.domain.models.scan.CardDTO
|
||||
import com.tangem.domain.models.scan.ScanResponse
|
||||
import com.tangem.domain.redux.ReduxStateHolder
|
||||
import com.tangem.domain.wallets.legacy.UserWalletsListManager
|
||||
import com.tangem.domain.wallets.legacy.WalletsStateHolder
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
|
|
@ -14,6 +15,7 @@ import com.tangem.tap.domain.walletStores.WalletStoresManager
|
|||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Store
|
||||
import javax.inject.Inject
|
||||
|
||||
|
|
@ -21,7 +23,7 @@ import javax.inject.Inject
|
|||
* Holds objects from old modules, that missing in DI graph.
|
||||
* Object sets manually to use in new modules and [AppStateHolder] proxies its to DI.
|
||||
*/
|
||||
class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationStateHolder {
|
||||
class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationStateHolder, ReduxStateHolder {
|
||||
|
||||
override var userWalletsListManager: UserWalletsListManager? = null
|
||||
set(value) {
|
||||
|
|
@ -50,4 +52,8 @@ class AppStateHolder @Inject constructor() : WalletsStateHolder, NavigationState
|
|||
override fun navigate(action: NavigationAction) {
|
||||
mainStore?.dispatch(action)
|
||||
}
|
||||
|
||||
override fun dispatch(action: Action) {
|
||||
mainStore?.dispatch(action)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ import com.tangem.domain.appcurrency.repository.AppCurrencyRepository
|
|||
import com.tangem.domain.card.ScanCardProcessor
|
||||
import com.tangem.domain.card.ScanCardUseCase
|
||||
import com.tangem.domain.card.repository.CardSdkConfigRepository
|
||||
import com.tangem.domain.walletmanager.WalletManagersFacade
|
||||
import com.tangem.features.tester.api.TesterRouter
|
||||
import com.tangem.features.tokendetails.featuretoggles.TokenDetailsFeatureToggles
|
||||
import com.tangem.features.tokendetails.navigation.TokenDetailsRouter
|
||||
|
|
@ -33,6 +34,7 @@ data class DaggerGraphState(
|
|||
val scanCardProcessor: ScanCardProcessor? = null,
|
||||
val cardSdkConfigRepository: CardSdkConfigRepository? = null,
|
||||
val appCurrencyRepository: AppCurrencyRepository? = null,
|
||||
val walletManagersFacade: WalletManagersFacade? = null,
|
||||
) : StateType {
|
||||
|
||||
inline fun <reified T> get(getDependency: DaggerGraphState.() -> T?): T {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue