Updated on 2026-08-14
This commit is contained in:
commit
2a62a36ab6
135 changed files with 893 additions and 596 deletions
|
|
@ -111,6 +111,7 @@ dependencies {
|
|||
implementation(fileTree(mapOf("dir" to "libs", "include" to listOf("*.aar"))))
|
||||
implementation(project(":domain"))
|
||||
implementation(project(":common"))
|
||||
implementation(project(":core:analytics"))
|
||||
implementation(project(":core:res"))
|
||||
implementation(project(":core:ui"))
|
||||
implementation(project(":core:datasource"))
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import androidx.core.view.WindowInsetsControllerCompat
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tangem.TangemSdk
|
||||
import com.tangem.domain.common.FeatureCoroutineExceptionHandler
|
||||
import com.tangem.utils.coroutines.FeatureCoroutineExceptionHandler
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tangem_sdk_new.extensions.init
|
||||
import com.tangem.tap.common.ActivityResultCallbackHolder
|
||||
|
|
@ -85,6 +85,7 @@ class MainActivity : AppCompatActivity(), SnackbarHandler, ActivityResultCallbac
|
|||
context = applicationContext,
|
||||
tangemSdkManager = tangemSdkManager,
|
||||
)
|
||||
appStateHolder.userWalletsListManager = userWalletsListManager
|
||||
userWalletsListManagerSafe = userWalletsListManager
|
||||
lockUserWalletsTimer = LockUserWalletsTimer(owner = this)
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import com.tangem.domain.common.LogConfig
|
|||
import com.tangem.tap.common.AndroidAssetReader
|
||||
import com.tangem.tap.common.AssetReader
|
||||
import com.tangem.tap.common.IntentHandler
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.AnalyticsFactory
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.filters.BasicSignInFilter
|
||||
|
|
@ -128,7 +128,6 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
middleware = AppState.getMiddleware(),
|
||||
state = AppState(),
|
||||
)
|
||||
appStateHolder.mainStore = store
|
||||
|
||||
if (BuildConfig.DEBUG) {
|
||||
Timber.plant(Timber.DebugTree())
|
||||
|
|
@ -155,7 +154,9 @@ class TapApplication : Application(), ImageLoaderFactory {
|
|||
context = this,
|
||||
tangemTechService = store.state.domainNetworks.tangemTechService,
|
||||
)
|
||||
appStateHolder.mainStore = store
|
||||
appStateHolder.userTokensRepository = userTokensRepository
|
||||
appStateHolder.walletStoresManager = walletStoresManager
|
||||
}
|
||||
|
||||
//todo refactor: move to datasource and provide via DI
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventLogger
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.ErrorEventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
import timber.log.Timber
|
||||
|
||||
class AnalyticsEventsLogger(
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
package com.tangem.tap.common.analytics
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptor
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package com.tangem.tap.common.analytics.api
|
||||
|
||||
import android.app.Application
|
||||
import com.tangem.common.json.MoshiJsonConverter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.domain.common.AnalyticsHandlersLogConfig
|
||||
import com.tangem.tap.domain.configurable.config.Config
|
||||
|
||||
interface AnalyticsHandlerBuilder {
|
||||
fun build(data: Data): AnalyticsHandler?
|
||||
|
||||
data class Data(
|
||||
val application: Application,
|
||||
val config: Config,
|
||||
val isDebug: Boolean,
|
||||
val logConfig: AnalyticsHandlersLogConfig,
|
||||
val jsonConverter: MoshiJsonConverter,
|
||||
)
|
||||
}
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.domain.features.addCustomToken.CustomCurrency
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
sealed class MyWallets(
|
||||
event: String,
|
||||
params: Map<String, String> = mapOf(),
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.features.details.ui.details.SocialNetwork
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam.CurrencyType
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.events
|
||||
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.persistence.ToppedUpWalletStorage
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
package com.tangem.tap.common.analytics.filters
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsEventFilter
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.analytics.handlers.appsFlyer.AppsFlyerAnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.handlers.firebase.FirebaseAnalyticsHandler
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.handlers.amplitude
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AmplitudeAnalyticsHandler(
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.app.Application
|
|||
import com.amplitude.api.Amplitude
|
||||
import com.amplitude.api.AmplitudeClient
|
||||
import com.tangem.common.Converter
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
import org.json.JSONObject
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.common.analytics.handlers.appsFlyer
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
|
||||
class AppsFlyerAnalyticsHandler(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.common.analytics.handlers.appsFlyer
|
|||
|
||||
import android.content.Context
|
||||
import com.appsflyer.AppsFlyerLib
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
package com.tangem.tap.common.analytics.handlers.firebase
|
||||
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.AnalyticsHandler
|
||||
import com.tangem.core.analytics.api.ErrorEventHandler
|
||||
import com.tangem.tap.common.analytics.api.AnalyticsHandlerBuilder
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventHandler
|
||||
import com.tangem.tap.common.analytics.converters.AnalyticsErrorConverter
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
|
||||
class FirebaseAnalyticsHandler(
|
||||
private val client: FirebaseAnalyticsClient,
|
||||
|
|
@ -17,18 +17,18 @@ class FirebaseAnalyticsHandler(
|
|||
}
|
||||
|
||||
override fun send(event: AnalyticsEvent) {
|
||||
when (event.error) {
|
||||
null -> super.send(event)
|
||||
else -> {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(event.error)) return
|
||||
val error = event.error
|
||||
if (error == null) {
|
||||
super.send(event)
|
||||
} else {
|
||||
val errorConverter = AnalyticsErrorConverter()
|
||||
if (!errorConverter.canBeHandled(error)) return
|
||||
|
||||
val errorParams = errorConverter.convert(event.error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(event.error, errorParams)
|
||||
}
|
||||
val errorParams = errorConverter.convert(error).toMutableMap()
|
||||
errorParams["Category"] = event.category
|
||||
errorParams["Event"] = event.event
|
||||
errorParams.putAll(event.params)
|
||||
send(error, errorParams)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ import com.google.firebase.analytics.FirebaseAnalytics
|
|||
import com.google.firebase.analytics.ktx.analytics
|
||||
import com.google.firebase.crashlytics.ktx.crashlytics
|
||||
import com.google.firebase.ktx.Firebase
|
||||
import com.tangem.tap.common.analytics.api.ErrorEventLogger
|
||||
import com.tangem.tap.common.analytics.api.EventLogger
|
||||
import com.tangem.analytics.api.ErrorEventLogger
|
||||
import com.tangem.analytics.api.EventLogger
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.common.analytics.paramsInterceptor
|
||||
|
||||
import com.tangem.tap.common.analytics.api.ParamsInterceptor
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsEvent
|
||||
import com.tangem.core.analytics.api.ParamsInterceptor
|
||||
import com.tangem.core.analytics.AnalyticsEvent
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.app.Application
|
|||
import android.content.Intent
|
||||
import com.google.android.gms.wallet.PaymentData
|
||||
import com.shopify.buy3.Storefront
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.converters.ShopOrderToEventConverter
|
||||
import com.tangem.tap.common.extensions.filterNotNull
|
||||
import com.tangem.tap.common.shop.data.ProductType
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import com.tangem.operations.derivation.DeriveMultipleWalletPublicKeysTask
|
|||
import com.tangem.operations.pins.CheckUserCodesCommand
|
||||
import com.tangem.operations.pins.CheckUserCodesResponse
|
||||
import com.tangem.operations.pins.SetUserCodeCommand
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Basic
|
||||
import com.tangem.tap.domain.tasks.CreateWalletAndRescanTask
|
||||
import com.tangem.tap.domain.tasks.product.CreateProductWalletTask
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
package com.tangem.tap.domain.configurable.config
|
||||
|
||||
import com.tangem.blockchain.common.BlockchainSdkConfig
|
||||
import com.tangem.blockchain.common.BlockchairCredentials
|
||||
import com.tangem.blockchain.common.QuickNodeCredentials
|
||||
import com.tangem.tap.common.shop.shopify.ShopifyShop
|
||||
import com.tangem.tap.common.zendesk.ZendeskConfig
|
||||
import com.tangem.tap.domain.configurable.Loader
|
||||
|
|
@ -84,9 +86,19 @@ class ConfigManager {
|
|||
mercuryoWidgetId = values.mercuryoWidgetId,
|
||||
mercuryoSecret = values.mercuryoSecret,
|
||||
blockchainSdkConfig = BlockchainSdkConfig(
|
||||
blockchairApiKey = values.blockchairApiKey,
|
||||
blockchairAuthorizationToken = values.blockchairAuthorizationToken,
|
||||
blockchairCredentials = BlockchairCredentials(
|
||||
apiKey = values.blockchairApiKeys,
|
||||
authToken = values.blockchairAuthorizationToken,
|
||||
),
|
||||
blockcypherTokens = values.blockcypherTokens,
|
||||
quickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = values.quiknodeApiKey,
|
||||
subdomain = values.quiknodeSubdomain,
|
||||
),
|
||||
bscQuickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = values.bscQuiknodeApiKey,
|
||||
subdomain = values.bscQuiknodeSubdomain,
|
||||
),
|
||||
infuraProjectId = values.infuraProjectId,
|
||||
tronGridApiKey = values.tronGridApiKey,
|
||||
saltPayAuthToken = values.saltPay.credentials.token,
|
||||
|
|
@ -104,9 +116,19 @@ class ConfigManager {
|
|||
mercuryoWidgetId = values.mercuryoWidgetId,
|
||||
mercuryoSecret = values.mercuryoSecret,
|
||||
blockchainSdkConfig = BlockchainSdkConfig(
|
||||
blockchairApiKey = values.blockchairApiKey,
|
||||
blockchairAuthorizationToken = values.blockchairAuthorizationToken,
|
||||
blockchairCredentials = BlockchairCredentials(
|
||||
apiKey = values.blockchairApiKeys,
|
||||
authToken = values.blockchairAuthorizationToken,
|
||||
),
|
||||
blockcypherTokens = values.blockcypherTokens,
|
||||
quickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = values.quiknodeApiKey,
|
||||
subdomain = values.quiknodeSubdomain,
|
||||
),
|
||||
bscQuickNodeCredentials = QuickNodeCredentials(
|
||||
apiKey = values.bscQuiknodeApiKey,
|
||||
subdomain = values.bscQuiknodeSubdomain,
|
||||
),
|
||||
infuraProjectId = values.infuraProjectId,
|
||||
saltPayAuthToken = values.saltPay.credentials.token,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -21,8 +21,12 @@ class ConfigValueModel(
|
|||
val mercuryoSecret: String,
|
||||
val moonPayApiKey: String,
|
||||
val moonPayApiSecretKey: String,
|
||||
val blockchairApiKey: String?,
|
||||
val blockchairApiKeys: List<String>,
|
||||
val blockchairAuthorizationToken: String?,
|
||||
val quiknodeSubdomain: String,
|
||||
val quiknodeApiKey: String,
|
||||
val bscQuiknodeSubdomain: String,
|
||||
val bscQuiknodeApiKey: String,
|
||||
val blockcypherTokens: Set<String>?,
|
||||
val infuraProjectId: String?,
|
||||
val appsFlyerDevKey: String,
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ val CardDTO.isMultiwalletAllowed: Boolean
|
|||
val CardDTO.isHdWalletAllowedByApp: Boolean
|
||||
get() = settings.isHDWalletAllowed && !isSaltPay
|
||||
|
||||
val CardDTO.isTangemWallet: Boolean
|
||||
get() = settings.isBackupAllowed
|
||||
&& settings.isHDWalletAllowed
|
||||
&& firmwareVersion >= FirmwareVersion.MultiWalletAvailable
|
||||
&& !isSaltPay
|
||||
|
||||
fun CardDTO.hasSignedHashes(): Boolean {
|
||||
return wallets.any { (it.totalSignedHashes ?: 0) > 0 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ class UserWalletBuilder(
|
|||
ProductType.Note -> "Note"
|
||||
ProductType.Twins -> "Twin"
|
||||
ProductType.SaltPay -> "SaltPay"
|
||||
ProductType.Start2Coin -> "Start2Coin"
|
||||
ProductType.Wallet -> when {
|
||||
card.isBackupNotAllowed -> "Tangem card"
|
||||
card.isStart2Coin -> "Start2Coin"
|
||||
|
|
@ -41,6 +42,7 @@ class UserWalletBuilder(
|
|||
ProductType.Note -> false
|
||||
ProductType.Twins -> false
|
||||
ProductType.SaltPay -> false
|
||||
ProductType.Start2Coin -> false
|
||||
ProductType.Wallet -> when {
|
||||
card.isStart2Coin -> false
|
||||
card.firmwareVersion >= FirmwareVersion.MultiWalletAvailable -> true
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ class UserWalletIdBuilder private constructor(
|
|||
ProductType.Note,
|
||||
ProductType.Wallet,
|
||||
ProductType.SaltPay,
|
||||
ProductType.Start2Coin,
|
||||
-> null
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.domain.common.extensions.withMainContext
|
|||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.analytics.paramsInterceptor.BatchIdParamsInterceptor
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
|
|
@ -21,9 +21,10 @@ import com.tangem.tap.common.redux.AppDialog
|
|||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.disclaimer.DisclaimerType
|
||||
import com.tangem.tap.features.disclaimer.createDisclaimer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerType
|
||||
import com.tangem.tap.features.disclaimer.redux.isAccepted
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerCallback
|
||||
import com.tangem.tap.features.onboarding.OnboardingHelper
|
||||
import com.tangem.tap.features.onboarding.OnboardingSaltPayHelper
|
||||
import com.tangem.tap.features.onboarding.products.twins.redux.TwinCardsAction
|
||||
|
|
@ -48,7 +49,8 @@ object ScanCardProcessor {
|
|||
cardId: String? = null,
|
||||
onProgressStateChange: suspend (showProgress: Boolean) -> Unit = {},
|
||||
onScanStateChange: suspend (scanInProgress: Boolean) -> Unit = {},
|
||||
onWalletNotCreated: suspend (() -> Unit) = {},
|
||||
onWalletNotCreated: suspend () -> Unit = {},
|
||||
disclaimerWillShow: () -> Unit = {},
|
||||
onFailure: suspend (error: TangemError) -> Unit = {},
|
||||
onSuccess: suspend (scanResponse: ScanResponse) -> Unit = {},
|
||||
) = withMainContext {
|
||||
|
|
@ -83,6 +85,8 @@ object ScanCardProcessor {
|
|||
showDisclaimerIfNeed(
|
||||
scanResponse = scanResponse1,
|
||||
onProgressStateChange = onProgressStateChange,
|
||||
disclaimerWillShow = disclaimerWillShow,
|
||||
onFailure = onFailure,
|
||||
nextHandler = { scanResponse2 ->
|
||||
onScanSuccess(
|
||||
scanResponse = scanResponse2,
|
||||
|
|
@ -128,28 +132,35 @@ object ScanCardProcessor {
|
|||
|
||||
private suspend inline fun showDisclaimerIfNeed(
|
||||
scanResponse: ScanResponse,
|
||||
crossinline disclaimerWillShow: () -> Unit = {},
|
||||
crossinline onProgressStateChange: suspend (showProgress: Boolean) -> Unit,
|
||||
crossinline nextHandler: suspend (ScanResponse) -> Unit,
|
||||
crossinline onFailure: suspend (error: TangemError) -> Unit,
|
||||
) {
|
||||
val disclaimerType = DisclaimerType.get(scanResponse)
|
||||
store.dispatchOnMain(DisclaimerAction.SetDisclaimerType(disclaimerType))
|
||||
val disclaimer = DisclaimerType.get(scanResponse.card).createDisclaimer(scanResponse.card)
|
||||
store.dispatchOnMain(DisclaimerAction.SetDisclaimer(disclaimer))
|
||||
|
||||
if (disclaimerType.isAccepted()) {
|
||||
if (disclaimer.isAccepted()) {
|
||||
nextHandler((scanResponse))
|
||||
} else scope.launch(Dispatchers.Main) {
|
||||
} else scope.launch {
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
store.dispatchOnMain(
|
||||
disclaimerWillShow()
|
||||
dispatchOnMain(
|
||||
DisclaimerAction.Show(
|
||||
onAcceptCallback = {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
nextHandler(scanResponse)
|
||||
}
|
||||
},
|
||||
onDismissCallback = {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
onProgressStateChange(false)
|
||||
}
|
||||
},
|
||||
fromScreen = AppScreen.Home,
|
||||
callback = DisclaimerCallback(
|
||||
onAccept = {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
nextHandler(scanResponse)
|
||||
}
|
||||
},
|
||||
onDismiss = {
|
||||
scope.launch(Dispatchers.Main) {
|
||||
onProgressStateChange(false)
|
||||
onFailure(TangemSdkError.UserCancelled())
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ import com.tangem.domain.common.ScanResponse
|
|||
import com.tangem.domain.common.TapWorkarounds.isExcluded
|
||||
import com.tangem.domain.common.TapWorkarounds.isNotSupportedInThatRelease
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemNote
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
|
||||
|
|
@ -193,8 +194,9 @@ private class ScanWalletProcessor(
|
|||
session: CardSession,
|
||||
callback: (result: CompletionResult<ScanResponse>) -> Unit,
|
||||
) {
|
||||
val productType = when (card.isSaltPay) {
|
||||
true -> ProductType.SaltPay
|
||||
val productType = when {
|
||||
card.isSaltPay -> ProductType.SaltPay
|
||||
card.isStart2Coin -> ProductType.Start2Coin
|
||||
else -> ProductType.Wallet
|
||||
}
|
||||
scope.launch {
|
||||
|
|
@ -264,12 +266,7 @@ private class ScanWalletProcessor(
|
|||
}
|
||||
if (additionalBlockchainsToDerive != null) {
|
||||
blockchainsToDerive.addAll(
|
||||
additionalBlockchainsToDerive.map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
card = card,
|
||||
)
|
||||
},
|
||||
additionalBlockchainsToDerive.map { BlockchainNetwork(it, card) }
|
||||
)
|
||||
}
|
||||
if (!card.useOldStyleDerivation) {
|
||||
|
|
@ -280,12 +277,7 @@ private class ScanWalletProcessor(
|
|||
Blockchain.RSK,
|
||||
Blockchain.Fantom, Blockchain.FantomTestnet,
|
||||
Blockchain.Avalanche, Blockchain.AvalancheTestnet,
|
||||
).map {
|
||||
BlockchainNetwork(
|
||||
blockchain = it,
|
||||
card = card,
|
||||
)
|
||||
},
|
||||
).map { BlockchainNetwork(it, card) },
|
||||
)
|
||||
}
|
||||
return blockchainsToDerive.distinct()
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
package com.tangem.tap.domain.termsOfUse
|
||||
|
||||
import android.content.res.Resources
|
||||
import android.net.Uri
|
||||
import androidx.core.os.ConfigurationCompat
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
class CardTou {
|
||||
private val locale: Locale =
|
||||
ConfigurationCompat.getLocales(Resources.getSystem().configuration).get(0)!!
|
||||
|
||||
fun getUrl(card: CardDTO): Uri? {
|
||||
val issuerName = card.issuer.name
|
||||
if (issuerName.lowercase(Locale.getDefault()) != "start2coin") return null
|
||||
|
||||
val baseUrl = "https://app.tangem.com/tou/"
|
||||
val regionCode = regionCode(card.cardId) ?: "fr"
|
||||
val filename = filename(locale.language, regionCode)
|
||||
return Uri.parse(baseUrl + filename)
|
||||
}
|
||||
|
||||
private fun filename(languageCode: String, regionCode: String): String {
|
||||
return when {
|
||||
languageCode == "fr" && regionCode == "ch" -> "Start2Coin-fr-ch-tangem.pdf"
|
||||
languageCode == "de" && regionCode == "ch" -> "Start2Coin-de-ch-tangem.pdf"
|
||||
languageCode == "en" && regionCode == "ch" -> "Start2Coin-en-ch-tangem.pdf"
|
||||
languageCode == "it" && regionCode == "ch" -> "Start2Coin-it-ch-tangem.pdf"
|
||||
languageCode == "fr" && regionCode == "fr" -> "Start2Coin-fr-fr-atangem.pdf"
|
||||
languageCode == "de" && regionCode == "at" -> "Start2Coin-de-at-tangem.pdf"
|
||||
regionCode == "fr" -> "Start2Coin-fr-fr-atangem.pdf"
|
||||
regionCode == "ch" -> "Start2Coin-en-ch-tangem.pdf"
|
||||
regionCode == "at" -> "Start2Coin-de-at-tangem.pdf"
|
||||
else -> "Start2Coin-fr-fr-atangem.pdf"
|
||||
}
|
||||
}
|
||||
|
||||
private fun regionCode(cardId: String): String? = when (cardId[1]) {
|
||||
'0' -> "fr"
|
||||
'1' -> "ch"
|
||||
'2' -> "at"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
|
@ -4,7 +4,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.common.card.EllipticCurve
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.WalletConnect
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.redux.global.GlobalAction
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import com.tangem.common.extensions.toDecompressedPublicKey
|
|||
import com.tangem.common.extensions.toHexString
|
||||
import com.tangem.crypto.CryptoUtils
|
||||
import com.tangem.operations.sign.SignHashCommand
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.WalletConnect
|
||||
import com.tangem.tap.common.extensions.safeUpdate
|
||||
import com.tangem.tap.common.extensions.toFormattedString
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.tangem.blockchain.common.Wallet
|
|||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.domain.termsOfUse.CardTou
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed class DetailsAction : Action {
|
||||
|
|
@ -12,10 +11,8 @@ sealed class DetailsAction : Action {
|
|||
data class PrepareScreen(
|
||||
val scanResponse: ScanResponse,
|
||||
val wallets: List<Wallet>,
|
||||
val cardTou: CardTou,
|
||||
) : DetailsAction()
|
||||
|
||||
object ShowDisclaimer : DetailsAction()
|
||||
object ReCreateTwinsWallet : DetailsAction()
|
||||
|
||||
sealed class ResetToFactory : DetailsAction() {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.common.doOnFailure
|
|||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.flatMap
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
|
|
@ -61,12 +61,6 @@ class DetailsMiddleware {
|
|||
is DetailsAction.ResetToFactory -> eraseWalletMiddleware.handle(action)
|
||||
is DetailsAction.ManageSecurity -> manageSecurityMiddleware.handle(action)
|
||||
is DetailsAction.AppSettings -> managePrivacyMiddleware.handle(state, action)
|
||||
is DetailsAction.ShowDisclaimer -> {
|
||||
val uri = state.cardTermsOfUseUrl
|
||||
if (uri != null) {
|
||||
store.dispatch(NavigationAction.OpenDocument(uri))
|
||||
}
|
||||
}
|
||||
is DetailsAction.ReCreateTwinsWallet -> {
|
||||
store.dispatch(TwinCardsAction.SetMode(CreateTwinWalletMode.RecreateWallet))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.OnboardingTwins))
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ private fun handlePrepareScreen(
|
|||
return DetailsState(
|
||||
scanResponse = action.scanResponse,
|
||||
wallets = action.wallets,
|
||||
cardTermsOfUseUrl = action.cardTou.getUrl(action.scanResponse.card),
|
||||
createBackupAllowed = action.scanResponse.card.backupStatus == CardDTO.BackupStatus.NoBackup,
|
||||
appCurrency = store.state.globalState.appCurrency,
|
||||
isBiometricsAvailable = tangemSdkManager.canUseBiometry,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
package com.tangem.tap.features.details.redux
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.blockchain.common.Wallet
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
|
|
@ -16,7 +15,6 @@ data class DetailsState(
|
|||
val scanResponse: ScanResponse? = null,
|
||||
val wallets: List<Wallet> = emptyList(),
|
||||
val cardSettingsState: CardSettingsState? = null,
|
||||
val cardTermsOfUseUrl: Uri? = null,
|
||||
val privacyPolicyUrl: String? = null,
|
||||
val createBackupAllowed: Boolean = false,
|
||||
val appCurrency: FiatCurrency = FiatCurrency.Default,
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.features.details.ui.cardsettings
|
|||
|
||||
import com.tangem.domain.common.TapWorkarounds.isTangemTwins
|
||||
import com.tangem.domain.common.getTwinCardIdForUser
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import androidx.fragment.app.Fragment
|
||||
import androidx.transition.TransitionInflater
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.features.details.redux.DetailsState
|
||||
|
|
|
|||
|
|
@ -29,7 +29,6 @@ enum class SettingsElement(
|
|||
AppSettings(R.drawable.ic_settings, R.string.app_settings_title),
|
||||
LinkMoreCards(R.drawable.ic_more_cards, R.string.details_row_title_create_backup),
|
||||
TermsOfService(R.drawable.ic_text, R.string.disclaimer_title), // General Terms of Service of the App
|
||||
TermsOfUse(R.drawable.ic_text, R.string.details_row_title_card_tou), // Terms of Use for S2C cards only
|
||||
PrivacyPolicy(R.drawable.ic_lock_24, R.string.details_row_privacy_policy);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.features.details.ui.details
|
|||
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.feedback.FeedbackEmail
|
||||
import com.tangem.tap.common.feedback.SupportInfo
|
||||
|
|
@ -38,7 +38,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
}
|
||||
SettingsElement.AppSettings -> if (state.isBiometricsAvailable) it else null
|
||||
SettingsElement.AppCurrency -> if (state.scanResponse?.card?.isMultiwalletAllowed != true) it else null
|
||||
SettingsElement.TermsOfUse -> if (state.scanResponse?.card?.isStart2Coin == true) it else null
|
||||
// SettingsElement.ReferralProgram -> if (state.scanResponse?.card?.isTangemWallet == true) it else null
|
||||
else -> it
|
||||
}
|
||||
}
|
||||
|
|
@ -87,10 +87,7 @@ class DetailsViewModel(private val store: Store<AppState>) {
|
|||
store.dispatch(DetailsAction.CreateBackup)
|
||||
}
|
||||
SettingsElement.TermsOfService -> {
|
||||
store.dispatch(DisclaimerAction.Show())
|
||||
}
|
||||
SettingsElement.TermsOfUse -> {
|
||||
store.dispatch(DetailsAction.ShowDisclaimer)
|
||||
store.dispatch(DisclaimerAction.Show(AppScreen.Details))
|
||||
}
|
||||
SettingsElement.PrivacyPolicy -> {
|
||||
// TODO: To be available later
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Settings
|
||||
import com.tangem.tap.common.compose.TangemTypography
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
|
|
|
|||
|
|
@ -0,0 +1,80 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import android.net.Uri
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface Disclaimer {
|
||||
fun type(): DisclaimerType
|
||||
fun getUri(): Uri
|
||||
fun accept()
|
||||
fun isAccepted(): Boolean
|
||||
}
|
||||
|
||||
abstract class BaseDisclaimer(
|
||||
protected val dataProvider: DisclaimerDataProvider,
|
||||
) : Disclaimer {
|
||||
|
||||
val baseUrl = "https://tangem.com"
|
||||
|
||||
override fun accept() {
|
||||
dataProvider.storage().accept(getPreferenceKey())
|
||||
}
|
||||
|
||||
override fun isAccepted(): Boolean = dataProvider.storage().isAccepted(getPreferenceKey())
|
||||
|
||||
protected open fun getPreferenceKey(): String = type().name
|
||||
}
|
||||
|
||||
class DummyDisclaimer : Disclaimer {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Tangem
|
||||
override fun getUri(): Uri = Uri.parse("https://tangem.com/tangem_tos.html")
|
||||
override fun accept() {}
|
||||
override fun isAccepted(): Boolean = false
|
||||
}
|
||||
|
||||
class TangemDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Tangem
|
||||
override fun getUri(): Uri = Uri.parse("$baseUrl/tangem_tos.html")
|
||||
override fun getPreferenceKey(): String = "tangem_tos_accepted"
|
||||
}
|
||||
|
||||
class SaltPayDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) {
|
||||
override fun type(): DisclaimerType = DisclaimerType.SaltPay
|
||||
override fun getUri(): Uri = Uri.parse("$baseUrl/soltpay_tos.html")
|
||||
override fun getPreferenceKey(): String = "saltPay_tos_accepted"
|
||||
}
|
||||
|
||||
class Start2CoinDisclaimer(dataProvider: DisclaimerDataProvider) : BaseDisclaimer(dataProvider) {
|
||||
override fun type(): DisclaimerType = DisclaimerType.Start2Coin
|
||||
override fun getUri(): Uri = Uri.parse("$baseUrl/" + filename(dataProvider.getLanguage(), getRegion()))
|
||||
override fun getPreferenceKey(): String = "start2Coin_tos_accepted_${getRegion()}"
|
||||
|
||||
private fun filename(languageCode: String, regionCode: String?): String {
|
||||
return when {
|
||||
languageCode == "fr" && regionCode == "ch" -> "Start2Coin-fr-ch-tangem.html"
|
||||
languageCode == "de" && regionCode == "ch" -> "Start2Coin-de-ch-tangem.html"
|
||||
languageCode == "en" && regionCode == "ch" -> "Start2Coin-en-ch-tangem.html"
|
||||
languageCode == "it" && regionCode == "ch" -> "Start2Coin-it-ch-tangem.html"
|
||||
languageCode == "fr" && regionCode == "fr" -> "Start2Coin-fr-fr-atangem.html"
|
||||
languageCode == "de" && regionCode == "at" -> "Start2Coin-de-at-tangem.html"
|
||||
regionCode == "fr" -> "Start2Coin-fr-fr-atangem.html"
|
||||
regionCode == "ch" -> "Start2Coin-en-ch-tangem.html"
|
||||
regionCode == "at" -> "Start2Coin-de-at-tangem.html"
|
||||
else -> "Start2Coin-fr-fr-atangem.html"
|
||||
}
|
||||
}
|
||||
|
||||
private fun getRegion(): String? {
|
||||
val cardId = dataProvider.getCardId()
|
||||
if (cardId.isEmpty()) return null
|
||||
|
||||
return when (cardId[1]) {
|
||||
'0' -> "fr"
|
||||
'1' -> "ch"
|
||||
'2' -> "at"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import com.tangem.tap.persistence.DisclaimerPrefStorage
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
interface DisclaimerDataProvider {
|
||||
fun getLanguage(): String
|
||||
fun getCardId(): String
|
||||
fun storage(): DisclaimerPrefStorage
|
||||
}
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
package com.tangem.tap.features.disclaimer
|
||||
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.tap.persistence.DisclaimerPrefStorage
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
[REDACTED_AUTHOR]
|
||||
*/
|
||||
enum class DisclaimerType {
|
||||
Tangem,
|
||||
SaltPay,
|
||||
Start2Coin;
|
||||
|
||||
companion object {
|
||||
fun get(cardDTO: CardDTO): DisclaimerType {
|
||||
return when {
|
||||
cardDTO.isSaltPay -> SaltPay
|
||||
cardDTO.isStart2Coin -> Start2Coin
|
||||
else -> Tangem
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DisclaimerType.createDisclaimer(cardDTO: CardDTO): Disclaimer {
|
||||
val dataProvider = provideDisclaimerDataProvider(cardDTO.cardId)
|
||||
return when (this) {
|
||||
DisclaimerType.Tangem -> TangemDisclaimer(dataProvider)
|
||||
DisclaimerType.SaltPay -> SaltPayDisclaimer(dataProvider)
|
||||
DisclaimerType.Start2Coin -> Start2CoinDisclaimer(dataProvider)
|
||||
}
|
||||
}
|
||||
|
||||
private fun provideDisclaimerDataProvider(cardId: String): DisclaimerDataProvider {
|
||||
return object : DisclaimerDataProvider {
|
||||
override fun getLanguage(): String = Locale.getDefault().language
|
||||
override fun getCardId(): String = cardId
|
||||
override fun storage(): DisclaimerPrefStorage = preferencesStorage.disclaimerPrefStorage
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +1,21 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.features.disclaimer.Disclaimer
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import org.rekotlin.Action
|
||||
|
||||
sealed class DisclaimerAction : Action {
|
||||
|
||||
data class SetDisclaimerType(
|
||||
val type: DisclaimerType,
|
||||
) : DisclaimerAction()
|
||||
data class SetDisclaimer(val disclaimer: Disclaimer) : DisclaimerAction()
|
||||
|
||||
data class Show(
|
||||
val onAcceptCallback: VoidCallback? = null,
|
||||
val onDismissCallback: VoidCallback? = null,
|
||||
) : DisclaimerAction()
|
||||
|
||||
data class AcceptDisclaimer(val type: DisclaimerType) : DisclaimerAction()
|
||||
|
||||
internal data class UpdateState(val type: DisclaimerType, val accepted: Boolean) : DisclaimerAction()
|
||||
|
||||
internal data class SetCallbacks(
|
||||
val onAcceptCallback: VoidCallback? = null,
|
||||
val onDismissCallback: VoidCallback? = null,
|
||||
val fromScreen: AppScreen,
|
||||
val callback: DisclaimerCallback? = null,
|
||||
) : DisclaimerAction()
|
||||
|
||||
object AcceptDisclaimer : DisclaimerAction()
|
||||
object OnBackPressed : DisclaimerAction()
|
||||
|
||||
data class OnProgressStateChanged(val state: ProgressState?) : DisclaimerAction()
|
||||
}
|
||||
|
|
@ -3,7 +3,6 @@ package com.tangem.tap.features.disclaimer.redux
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
import com.tangem.tap.preferencesStorage
|
||||
import com.tangem.tap.store
|
||||
import org.rekotlin.Action
|
||||
import org.rekotlin.Middleware
|
||||
|
|
@ -23,49 +22,17 @@ private fun handleDisclaimerMiddleware(action: Action, appState: AppState) {
|
|||
val state = appState.disclaimerState
|
||||
|
||||
when (action) {
|
||||
is DisclaimerAction.SetDisclaimerType -> {
|
||||
handleUpdateState = action.type.createUpdateState()
|
||||
}
|
||||
is DisclaimerAction.Show -> {
|
||||
handleUpdateState = state.type.createUpdateState()
|
||||
store.dispatch(DisclaimerAction.SetCallbacks(action.onAcceptCallback, action.onDismissCallback))
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Disclaimer))
|
||||
}
|
||||
is DisclaimerAction.AcceptDisclaimer -> {
|
||||
action.type.accept()
|
||||
handleUpdateState = action.type.createUpdateState()
|
||||
state.disclaimer.accept()
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
state.onAcceptCallback?.invoke()
|
||||
store.dispatch(DisclaimerAction.SetCallbacks(null, null))
|
||||
state.callback?.onAccept?.invoke()
|
||||
}
|
||||
is DisclaimerAction.OnBackPressed -> {
|
||||
state.onDismissCallback?.invoke()
|
||||
store.dispatch(DisclaimerAction.SetCallbacks(null, null))
|
||||
store.dispatch(NavigationAction.PopBackTo())
|
||||
|
||||
state.callback?.onDismiss?.invoke()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun DisclaimerType.accept() = when (this) {
|
||||
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted = true
|
||||
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted = true
|
||||
}
|
||||
|
||||
fun DisclaimerType.isAccepted(): Boolean = when (this) {
|
||||
DisclaimerType.SaltPay -> preferencesStorage.disclaimerPrefStorage.hasSaltPayTosAccepted
|
||||
DisclaimerType.Tangem -> preferencesStorage.disclaimerPrefStorage.hasTangemTosAccepted
|
||||
}
|
||||
|
||||
private fun DisclaimerType.createUpdateState(): DisclaimerAction.UpdateState {
|
||||
return DisclaimerAction.UpdateState(this, this.isAccepted())
|
||||
}
|
||||
|
||||
private var handleUpdateState: DisclaimerAction.UpdateState = DisclaimerAction.UpdateState(
|
||||
type = DisclaimerType.Tangem,
|
||||
accepted = false,
|
||||
)
|
||||
set(value) {
|
||||
field = value
|
||||
store.dispatch(value)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,13 +15,19 @@ private fun internalReduce(action: Action, state: AppState): DisclaimerState {
|
|||
val disclaimerState = state.disclaimerState
|
||||
|
||||
return when (action) {
|
||||
is DisclaimerAction.UpdateState -> disclaimerState.copy(
|
||||
type = action.type,
|
||||
accepted = action.accepted,
|
||||
is DisclaimerAction.SetDisclaimer -> disclaimerState.copy(
|
||||
disclaimer = action.disclaimer,
|
||||
)
|
||||
is DisclaimerAction.SetCallbacks -> disclaimerState.copy(
|
||||
onAcceptCallback = action.onAcceptCallback,
|
||||
onDismissCallback = action.onDismissCallback,
|
||||
is DisclaimerAction.Show -> disclaimerState.copy(
|
||||
showedFromScreen = action.fromScreen,
|
||||
callback = action.callback,
|
||||
)
|
||||
is DisclaimerAction.AcceptDisclaimer, is DisclaimerAction.OnBackPressed -> disclaimerState.copy(
|
||||
callback = null,
|
||||
progressState = null,
|
||||
)
|
||||
is DisclaimerAction.OnProgressStateChanged -> disclaimerState.copy(
|
||||
progressState = action.state,
|
||||
)
|
||||
else -> disclaimerState
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,31 +1,21 @@
|
|||
package com.tangem.tap.features.disclaimer.redux
|
||||
|
||||
import android.net.Uri
|
||||
import com.tangem.common.extensions.VoidCallback
|
||||
import com.tangem.domain.common.CardDTO
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.features.disclaimer.Disclaimer
|
||||
import com.tangem.tap.features.disclaimer.DummyDisclaimer
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import org.rekotlin.StateType
|
||||
|
||||
data class DisclaimerState(
|
||||
val accepted: Boolean = false,
|
||||
val type: DisclaimerType = DisclaimerType.Tangem,
|
||||
val onAcceptCallback: VoidCallback? = null,
|
||||
val onDismissCallback: VoidCallback? = null,
|
||||
) : StateType
|
||||
val disclaimer: Disclaimer = DummyDisclaimer(),
|
||||
val showedFromScreen: AppScreen = AppScreen.Home,
|
||||
val callback: DisclaimerCallback? = null,
|
||||
val progressState: ProgressState? = null,
|
||||
) : StateType {
|
||||
}
|
||||
|
||||
sealed class DisclaimerType(
|
||||
val uri: Uri,
|
||||
) {
|
||||
object Tangem : DisclaimerType(Uri.parse("https://tangem.com/tangem_tos.html"))
|
||||
object SaltPay : DisclaimerType(Uri.parse("https://tangem.com/soltpay_tos.html"))
|
||||
|
||||
companion object {
|
||||
fun get(scanResponse: ScanResponse): DisclaimerType = get(scanResponse.card)
|
||||
|
||||
fun get(card: CardDTO): DisclaimerType = when {
|
||||
card.isSaltPay -> SaltPay
|
||||
else -> Tangem
|
||||
}
|
||||
}
|
||||
}
|
||||
data class DisclaimerCallback(
|
||||
val onAccept: VoidCallback? = null,
|
||||
val onDismiss: VoidCallback? = null,
|
||||
)
|
||||
|
|
@ -6,12 +6,17 @@ import androidx.transition.TransitionInflater
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.tangem.core.ui.fragments.setStatusBarColor
|
||||
import com.tangem.tap.common.extensions.configureSettings
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.features.BaseFragment
|
||||
import com.tangem.tap.features.addBackPressHandler
|
||||
import com.tangem.tap.features.disclaimer.Disclaimer
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerAction
|
||||
import com.tangem.tap.features.disclaimer.redux.DisclaimerState
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
import com.tangem.tap.store
|
||||
import com.tangem.wallet.R
|
||||
import com.tangem.wallet.databinding.FragmentDisclaimerBinding
|
||||
|
|
@ -20,21 +25,53 @@ import org.rekotlin.StoreSubscriber
|
|||
class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubscriber<DisclaimerState> {
|
||||
|
||||
private val binding: FragmentDisclaimerBinding by viewBinding(FragmentDisclaimerBinding::bind)
|
||||
private val webViewClient = DisclaimerWebViewClient()
|
||||
|
||||
override fun configureTransitions() {
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
when (store.state.disclaimerState.showedFromScreen) {
|
||||
AppScreen.Home -> {
|
||||
enterTransition = inflater.inflateTransition(android.R.transition.slide_bottom)
|
||||
exitTransition = inflater.inflateTransition(android.R.transition.slide_top)
|
||||
}
|
||||
AppScreen.Details -> {
|
||||
enterTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
exitTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
addBackPressHandler(handler = this)
|
||||
binding.toolbar.setNavigationOnClickListener { handleOnBackPressed() }
|
||||
binding.webView.apply {
|
||||
settings.allowFileAccess = false
|
||||
settings.javaScriptEnabled = false
|
||||
webViewClient = DisclaimerWebViewClient
|
||||
|
||||
binding.apply {
|
||||
toolbar.setNavigationOnClickListener { handleOnBackPressed() }
|
||||
webView.apply {
|
||||
settings.allowFileAccess = false
|
||||
settings.javaScriptEnabled = false
|
||||
webViewClient = this@DisclaimerFragment.webViewClient
|
||||
}
|
||||
webView.hide()
|
||||
groupError.hide()
|
||||
groupAccept.hide()
|
||||
groupLoading.hide()
|
||||
|
||||
btnAccept.setOnClickListener {
|
||||
store.dispatch(DisclaimerAction.AcceptDisclaimer)
|
||||
}
|
||||
btnRepeat.setOnClickListener {
|
||||
webViewClient.reset()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
setStatusBarColor(R.color.backgroundLightGray)
|
||||
|
||||
webViewClient.onProgressStateChanged = { store.dispatch(DisclaimerAction.OnProgressStateChanged(it)) }
|
||||
store.subscribe(subscriber = this) { state ->
|
||||
state
|
||||
.skipRepeats { oldState, newState -> oldState.disclaimerState == newState.disclaimerState }
|
||||
|
|
@ -43,30 +80,43 @@ class DisclaimerFragment : BaseFragment(R.layout.fragment_disclaimer), StoreSubs
|
|||
}
|
||||
|
||||
override fun onStop() {
|
||||
super.onStop()
|
||||
webViewClient.onProgressStateChanged = null
|
||||
store.unsubscribe(this)
|
||||
}
|
||||
|
||||
override fun configureTransitions() {
|
||||
super.configureTransitions()
|
||||
val inflater = TransitionInflater.from(requireContext())
|
||||
enterTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
exitTransition = inflater.inflateTransition(android.R.transition.fade)
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
override fun newState(state: DisclaimerState) = with(binding) {
|
||||
if (activity == null || view == null) return
|
||||
|
||||
if (state.accepted) {
|
||||
halfTransparentOverlay.hide()
|
||||
btnAccept.hide()
|
||||
}
|
||||
updateUiVisibility(state.disclaimer, state.progressState)
|
||||
binding.webView.loadUrl(state.disclaimer.getUri().toString())
|
||||
}
|
||||
|
||||
btnAccept.setOnClickListener {
|
||||
store.dispatch(DisclaimerAction.AcceptDisclaimer(state.type))
|
||||
private fun updateUiVisibility(disclaimer: Disclaimer, progressState: ProgressState?) = with(binding) {
|
||||
when (progressState) {
|
||||
ProgressState.Loading -> {
|
||||
root.beginDelayedTransition()
|
||||
webView.hide()
|
||||
groupError.hide()
|
||||
groupAccept.hide()
|
||||
groupLoading.show()
|
||||
}
|
||||
ProgressState.Done -> {
|
||||
root.beginDelayedTransition()
|
||||
groupError.hide()
|
||||
groupLoading.hide()
|
||||
webView.show()
|
||||
groupAccept.show(!disclaimer.isAccepted())
|
||||
}
|
||||
ProgressState.Error -> {
|
||||
root.beginDelayedTransition()
|
||||
webView.hide()
|
||||
groupAccept.hide()
|
||||
groupLoading.hide()
|
||||
groupError.show()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
|
||||
webView.loadUrl(state.type.uri.toString())
|
||||
}
|
||||
|
||||
override fun handleOnBackPressed() {
|
||||
|
|
|
|||
|
|
@ -1,100 +1,68 @@
|
|||
package com.tangem.tap.features.disclaimer.ui
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import android.webkit.WebResourceError
|
||||
import android.webkit.WebResourceRequest
|
||||
import android.webkit.WebResourceResponse
|
||||
import android.webkit.WebView
|
||||
import android.webkit.WebViewClient
|
||||
import com.tangem.common.extensions.ifNotNull
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
|
||||
object DisclaimerWebViewClient : WebViewClient() {
|
||||
class DisclaimerWebViewClient : WebViewClient() {
|
||||
|
||||
private const val HTML_MIME_TYPE = "text/html"
|
||||
private const val UTF8_ENCODING = "utf-8"
|
||||
var onProgressStateChanged: ((ProgressState) -> Unit)? = null
|
||||
|
||||
override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
|
||||
super.onReceivedError(view, request, error)
|
||||
view?.loadLocalContent()
|
||||
private var loadingUrl: String? = null
|
||||
private var loadedUrl: String? = null
|
||||
|
||||
private var progressState: ProgressState = ProgressState.Loading
|
||||
set(value) {
|
||||
field = value
|
||||
onProgressStateChanged?.invoke(value)
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
loadingUrl = null
|
||||
loadedUrl = null
|
||||
progressState = ProgressState.Loading
|
||||
}
|
||||
|
||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
||||
super.onPageStarted(view, url, favicon)
|
||||
|
||||
if (loadingUrl != url) progressState = ProgressState.Loading
|
||||
loadingUrl = url
|
||||
}
|
||||
|
||||
override fun onPageFinished(view: WebView?, url: String?) {
|
||||
super.onPageFinished(view, url)
|
||||
|
||||
if (loadedUrl != url) progressState = ProgressState.Done
|
||||
loadedUrl = url
|
||||
}
|
||||
|
||||
override fun onReceivedError(
|
||||
view: WebView?,
|
||||
resourceRequest: WebResourceRequest?,
|
||||
error: WebResourceError?,
|
||||
) {
|
||||
super.onReceivedError(view, resourceRequest, error)
|
||||
error?.let { progressState = ProgressState.Error }
|
||||
}
|
||||
|
||||
override fun onReceivedHttpError(
|
||||
view: WebView?,
|
||||
request: WebResourceRequest?,
|
||||
resourceRequest: WebResourceRequest?,
|
||||
errorResponse: WebResourceResponse?,
|
||||
) {
|
||||
super.onReceivedHttpError(view, request, errorResponse)
|
||||
view?.loadLocalContent()
|
||||
}
|
||||
super.onReceivedHttpError(view, resourceRequest, errorResponse)
|
||||
|
||||
private fun WebView?.loadLocalContent() {
|
||||
this?.loadDataWithBaseURL(null, TERMS_OF_SERVICE_HTML, HTML_MIME_TYPE, UTF8_ENCODING, null)
|
||||
}
|
||||
}
|
||||
ifNotNull(resourceRequest, errorResponse) { request, response ->
|
||||
if (request.url?.toString() != loadingUrl || response.statusCode < 400) return
|
||||
if (progressState != ProgressState.Done) return
|
||||
|
||||
private const val TERMS_OF_SERVICE_HTML =
|
||||
"""<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<title>Legal Disclaimer</title>
|
||||
<style>
|
||||
@font-face{font-family:"SF Pro Display";src:url(/fonts/sf-pro/SFProDisplay-Light.eot) format("embedded-opentype"),url(/fonts/sf-pro/SFProDisplay-Light.woff2) format("woff2"),url(/fonts/sf-pro/SFProDisplay-Light.woff) format("woff"),url(/fonts/sf-pro/SFProDisplay-Light.ttf) format("truetype");font-weight:300;font-style:normal;font-display:swap}@font-face{font-family:"SF Pro Display";src:url(/fonts/sf-pro/SFProDisplay-Regular.eot) format("embedded-opentype"),url(/fonts/sf-pro/SFProDisplay-Regular.woff2) format("woff2"),url(/fonts/sf-pro/SFProDisplay-Regular.woff) format("woff"),url(/fonts/sf-pro/SFProDisplay-Regular.ttf) format("truetype");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:"SF Pro Display";src:url(/fonts/sf-pro/SFProDisplay-Medium.eot) format("embedded-opentype"),url(/fonts/sf-pro/SFProDisplay-Medium.woff2) format("woff2"),url(/fonts/sf-pro/SFProDisplay-Medium.woff) format("woff"),url(/fonts/sf-pro/SFProDisplay-Medium.ttf) format("truetype");font-weight:500;font-style:normal;font-display:swap}@font-face{font-family:"SF Pro Display";src:url(/fonts/sf-pro/SFProDisplay-Semibold.eot) format("embedded-opentype"),url(/fonts/sf-pro/SFProDisplay-Semibold.woff2) format("woff2"),url(/fonts/sf-pro/SFProDisplay-Semibold.woff) format("woff"),url(/fonts/sf-pro/SFProDisplay-Semibold.ttf) format("truetype");font-weight:600;font-style:normal;font-display:swap}@font-face{font-family:"SF Pro Display";src:url(/fonts/sf-pro/SFProDisplay-Bold.eot) format("embedded-opentype"),url(/fonts/sf-pro/SFProDisplay-Bold.woff2) format("woff2"),url(/fonts/sf-pro/SFProDisplay-Bold.woff) format("woff"),url(/fonts/sf-pro/SFProDisplay-Bold.ttf) format("truetype");font-weight:700;font-style:normal;font-display:swap}*{margin:0;padding:0}body{padding:0;margin:1rem;color:rgb(0 0 0);font-family:'SF Pro Display',-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}h1{font-weight:700;font-size:30px;line-height:1.2;margin-bottom:1rem}p{font-size:16px;line-height:20px;letter-spacing:-.24px;margin-bottom:1rem}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Legal Disclaimer</h1>
|
||||
<p> 1. Tangem application (Software)</p>
|
||||
<p> The Software is intended for usage only with Tangem hardware wallets (Cards) via NFC interface. The
|
||||
Software DOES NOT:</p>
|
||||
<p> a) Generate, store, transmit, or have access to private (secret) cryptographic keys to
|
||||
blockchain
|
||||
wallets holding digital assets, including crypto-currency.</p>
|
||||
<p> b) Generate, store, transmit, or have access to secret keys, passwords, passphrases, recovery phrases
|
||||
that can be used to restore or to copy private (secret) keys to blockchain wallets holding digital assets, including
|
||||
crypto-currency.</p>
|
||||
<p> c) Provide exchange, trading, investment services on behalf of Tangem AG.</p>
|
||||
<p> 2. Risks related to the use of Software</p>
|
||||
<p> Tangem will not be responsible for any losses, damages or claims arising from events falling within the
|
||||
scope of the following five categories:</p>
|
||||
<p> a) Mistakes made by the user of any cryptocurrency-related software or service, e.g., forgotten
|
||||
passwords, payments sent to wrong addresses, and accidental deletion of blockchain wallets on Cards.</p>
|
||||
<p> b) Problems of Software and/or any blockchain- or cryptocurrency- related software or service, e.g.,
|
||||
corrupted files, incorrectly constructed transactions, unsafe cryptographic libraries, malware.</p>
|
||||
<p> c) Technical failures in the hardware of the user, including Cards, of any cryptocurrency-related
|
||||
software or service, e.g., data loss due to a faulty or damaged storage device.</p>
|
||||
<p> d) Security problems experienced by the user of any cryptocurrency-related software or
|
||||
service, e.g.,
|
||||
unauthorized access to users' wallets and/or accounts.</p>
|
||||
<p> e) Actions or inactions of third parties and/or events experienced by third parties, e.g., bankruptcy
|
||||
of service providers, information security attacks on service providers, and fraud conducted by third parties.</p>
|
||||
<p> 3. Trading and Investment risks</p>
|
||||
<p> There is considerable exposure to risk in any crypto-currency or other digital asset exchange
|
||||
transaction. Any transaction involving currencies involves risks including, but not limited to, the potential for
|
||||
changing economic conditions that may substantially affect the price or liquidity of a currency. Investments in
|
||||
crypto-currency exchange speculation may also be susceptible to sharp rises and falls as the relevant market values
|
||||
fluctuate. It is for this reason that when speculating in such markets it is advisable to use only risk capital.</p>
|
||||
<p> 4. Electronic Trading Risks</p>
|
||||
<p> Before you engage in transactions using an electronic system, you should carefully review the rules and
|
||||
regulations of the exchanges offering the system and/or listing the instruments you intend to trade. Online trading
|
||||
has inherent risk due to system response and access times that may vary due to market conditions, system
|
||||
performance, and other factors. You should understand these and additional risks before trading.</p>
|
||||
<p> 5. Compliance with tax obligations </p>
|
||||
<p> The users of the Software are solely responsible to determinate what, if any, taxes apply to their
|
||||
crypto-currency transactions. The owners of, or contributors to, the Software are NOT responsible for determining
|
||||
the taxes that apply to crypto-currency transactions. </p>
|
||||
<p> 6. No warranties </p>
|
||||
<p> The Software is provided on an "as is" basis without any warranties of any kind regarding the
|
||||
Software and/or any content, data, materials and/or services provided on the Software.
|
||||
</p>
|
||||
<p> 7. Limitation of liability</p>
|
||||
<p> Unless otherwise required by law, in no event shall the owners of, or contributors to, the Software be
|
||||
liable for any damages of any kind, including, but not limited to, loss of use, loss of profits, or loss of data
|
||||
arising out of or in any way connected with the use of the Software. In no way are the owners of, or contributors
|
||||
to, the Software responsible for the actions, decisions, or other behavior taken or not taken by you in reliance
|
||||
upon the Software.</p>
|
||||
<p> 8. Last amendment</p>
|
||||
<p> This disclaimer was amended for the last time on October 1st, 2020.</p>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
progressState = ProgressState.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -12,7 +12,7 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import androidx.core.view.WindowInsetsControllerCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.redux.navigation.AppScreen
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import android.os.Bundle
|
|||
import android.view.LayoutInflater
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ class OnboardingHelper {
|
|||
}
|
||||
ProductType.Twins -> AppScreen.OnboardingTwins
|
||||
ProductType.SaltPay -> AppScreen.OnboardingWallet
|
||||
ProductType.Start2Coin -> throw java.lang.UnsupportedOperationException(
|
||||
"Onboarding for Start2Coin cards is not supported"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import androidx.core.view.isVisible
|
|||
import androidx.transition.TransitionManager
|
||||
import coil.load
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.extensions.stripZeroPlainString
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import androidx.constraintlayout.widget.ConstraintSet
|
|||
import androidx.core.view.isVisible
|
||||
import androidx.transition.TransitionManager
|
||||
import coil.load
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
import com.tangem.tap.common.redux.navigation.ShareElement
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.blockchain.common.Blockchain
|
|||
import com.tangem.common.CompletionResult
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.postUi
|
||||
import com.tangem.tap.common.redux.AppState
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.tangem.common.extensions.guard
|
|||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import com.tangem.domain.common.ScanResponse
|
|||
import com.tangem.domain.common.TwinCardNumber
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tap.common.AndroidAssetReader
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.beginDelayedTransition
|
||||
import com.tangem.tap.common.extensions.getDrawableCompat
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.operations.backup.BackupService
|
||||
import com.tangem.tap.backupService
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ class GnosisRegistrator(
|
|||
}
|
||||
|
||||
private val otpProcessorContractAddress: String = when (walletManager.wallet.blockchain) {
|
||||
Blockchain.SaltPay -> "0xc659f4FEd7A84a188F54cBA4A7a49D77c1a20522"
|
||||
Blockchain.SaltPay -> "0x3B4397C817A26521Df8bD01a949AFDE2251d91C2"
|
||||
else -> throw IllegalArgumentException("GnosisRegistrator supports only the SaltPay blockchain")
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import com.tangem.domain.common.extensions.successOr
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.datasource.api.paymentology.KYCStatus
|
||||
import com.tangem.datasource.api.paymentology.RegistrationResponse
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ import coil.size.Scale
|
|||
import com.google.android.material.appbar.MaterialToolbar
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.compose.PinCodeWidget
|
||||
import com.tangem.tap.common.extensions.configureSettings
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import com.tangem.common.CardIdFormatter
|
|||
import com.tangem.common.core.CardIdDisplayFormat
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.LeapfrogWidget
|
||||
import com.tangem.tangem_sdk_new.ui.widget.leapfrogWidget.PropertyCalculator
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
import com.tangem.tap.common.extensions.inflate
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.tangem.common.CompletionResult
|
|||
import com.tangem.common.doOnFailure
|
||||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.flatMap
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import com.tangem.domain.common.CardDTO
|
|||
import com.tangem.domain.common.TapWorkarounds.isStart2Coin
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogShow
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.google.android.material.textfield.TextInputEditText
|
|||
import com.tangem.Message
|
||||
import com.tangem.tangem_sdk_new.extensions.hideSoftKeyboard
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
import com.tangem.tap.common.extensions.getFromClipboard
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import androidx.activity.OnBackPressedCallback
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.tangem.tap.common.GlobalLayoutStateHandler
|
||||
import com.tangem.tap.common.KeyboardObserver
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Shop
|
||||
import com.tangem.tap.common.extensions.show
|
||||
import com.tangem.tap.common.redux.navigation.NavigationAction
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import androidx.compose.ui.platform.ComposeView
|
|||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.domain.features.addCustomToken.redux.AddCustomTokenState
|
||||
import com.tangem.domain.redux.domainStore
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.compose.ClosePopupTrigger
|
||||
import com.tangem.tap.features.BaseStoreFragment
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.tangem.domain.redux.domainStore
|
|||
import com.tangem.operations.derivation.ExtendedPublicKeysMap
|
||||
import com.tangem.tap.DELAY_SDK_DIALOG_CLOSE
|
||||
import com.tangem.tap.assetReader
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import androidx.transition.TransitionInflater
|
|||
import by.kirich1409.viewbindingdelegate.viewBinding
|
||||
import com.google.accompanist.appcompattheme.AppCompatTheme
|
||||
import com.tangem.blockchain.common.Blockchain
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
import com.tangem.tap.common.extensions.dispatchNotification
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ import com.tangem.core.ui.components.SystemBarsEffect
|
|||
import com.tangem.core.ui.components.keyboardAsState
|
||||
import com.tangem.domain.common.TapWorkarounds.useOldStyleDerivation
|
||||
import com.tangem.domain.common.extensions.fromNetworkId
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.ManageTokens
|
||||
import com.tangem.tap.common.compose.extensions.addAndNotify
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.tangem.tap.features.wallet.redux.middlewares
|
||||
|
||||
import com.tangem.datasource.api.tangemTech.models.CurrenciesResponse
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.entities.FiatCurrency
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import com.tangem.blockchain.common.WalletManager
|
|||
import com.tangem.common.doOnSuccess
|
||||
import com.tangem.common.extensions.guard
|
||||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Token.ButtonRemoveToken
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ package com.tangem.tap.features.wallet.redux.middlewares
|
|||
import androidx.core.os.bundleOf
|
||||
import com.tangem.blockchain.blockchains.ethereum.EthereumWalletManager
|
||||
import com.tangem.blockchain.common.AmountType
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.domain.common.extensions.toNetworkId
|
||||
import com.tangem.feature.swap.presentation.SwapFragment
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDebugErrorNotification
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
package com.tangem.tap.features.wallet.redux.middlewares
|
||||
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import com.tangem.common.services.Result
|
|||
import com.tangem.domain.common.extensions.withMainContext
|
||||
import com.tangem.operations.attestation.Attestation
|
||||
import com.tangem.operations.attestation.OnlineCardVerifier
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.copyToClipboard
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
|||
import com.tangem.tangem_sdk_new.extensions.dpToPx
|
||||
import com.tangem.tap.common.SnackbarHandler
|
||||
import com.tangem.tap.common.TestActions
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.DetailsScreen
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
import com.tangem.tap.common.extensions.appendIfNotNull
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import com.tangem.core.ui.fragments.setStatusBarColor
|
|||
import com.tangem.core.ui.utils.OneTouchClickListener
|
||||
import com.tangem.domain.common.TapWorkarounds.isSaltPay
|
||||
import com.tangem.tap.MainActivity
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.converters.BasicSignInEventConverter
|
||||
import com.tangem.tap.common.analytics.converters.BasicTopUpEventConverter
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
|
|
@ -34,7 +34,6 @@ import com.tangem.tap.common.redux.navigation.NavigationAction
|
|||
import com.tangem.tap.domain.configurable.warningMessage.WarningMessage
|
||||
import com.tangem.tap.domain.statePrinter.printScanResponseState
|
||||
import com.tangem.tap.domain.statePrinter.printWalletState
|
||||
import com.tangem.tap.domain.termsOfUse.CardTou
|
||||
import com.tangem.tap.features.details.redux.DetailsAction
|
||||
import com.tangem.tap.features.wallet.redux.ErrorType
|
||||
import com.tangem.tap.features.wallet.redux.ProgressState
|
||||
|
|
@ -245,7 +244,6 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), StoreSubscriber<Walle
|
|||
DetailsAction.PrepareScreen(
|
||||
scanResponse = scanNoteResponse,
|
||||
wallets = store.state.walletState.walletManagers.map { it.wallet },
|
||||
cardTou = CardTou(),
|
||||
),
|
||||
)
|
||||
store.dispatch(NavigationAction.NavigateTo(AppScreen.Details))
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.Portfolio
|
||||
import com.tangem.tap.common.extensions.getString
|
||||
import com.tangem.tap.common.extensions.hide
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import androidx.recyclerview.widget.DiffUtil
|
|||
import androidx.recyclerview.widget.ListAdapter
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.play.core.review.ReviewManagerFactory
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.extensions.getActivity
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.AnalyticsParam
|
||||
import com.tangem.tap.common.analytics.events.Onboarding
|
||||
import com.tangem.tap.common.analytics.events.Token
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.tangem.tap.features.wallet.ui.dialogs
|
|||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.IntroductionProcess
|
||||
import com.tangem.tap.common.extensions.dispatchDialogHide
|
||||
import com.tangem.tap.common.feedback.ScanFailsEmail
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import com.badoo.mvicore.DiffStrategy
|
|||
import com.badoo.mvicore.modelWatcher
|
||||
import com.tangem.domain.common.TapWorkarounds.derivationStyle
|
||||
import com.tangem.domain.common.TapWorkarounds.isTestCard
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MainScreen
|
||||
import com.tangem.tap.common.analytics.events.Portfolio
|
||||
import com.tangem.tap.common.extensions.animateVisibility
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import com.tangem.common.flatMap
|
|||
import com.tangem.common.map
|
||||
import com.tangem.domain.common.ScanResponse
|
||||
import com.tangem.domain.common.util.UserWalletId
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
import com.tangem.tap.common.analytics.events.MyWallets
|
||||
import com.tangem.tap.common.extensions.dispatchOnMain
|
||||
import com.tangem.tap.common.extensions.onUserWalletSelected
|
||||
|
|
@ -139,7 +139,16 @@ internal class WalletSelectorMiddleware {
|
|||
tangemSdkManager.setAccessCodeRequestPolicy(
|
||||
useBiometricsForAccessCode = preferencesStorage.shouldSaveAccessCodes,
|
||||
)
|
||||
|
||||
ScanCardProcessor.scan(
|
||||
onWalletNotCreated = {
|
||||
// No need to rollback policy, continue with the policy set before the card scan
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
},
|
||||
disclaimerWillShow = {
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo())
|
||||
},
|
||||
onSuccess = { scanResponse ->
|
||||
saveUserWalletAndPopBackToWalletScreen(scanResponse)
|
||||
.doOnFailure { error ->
|
||||
|
|
@ -153,11 +162,6 @@ internal class WalletSelectorMiddleware {
|
|||
tangemSdkManager.setAccessCodeRequestPolicy(prevUseBiometricsForAccessCode)
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Error(error))
|
||||
},
|
||||
onWalletNotCreated = {
|
||||
// No need to rollback policy, continue with the policy set before the card scan
|
||||
store.dispatchOnMain(WalletSelectorAction.AddWallet.Success)
|
||||
store.dispatchOnMain(NavigationAction.PopBackTo(AppScreen.Wallet))
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import androidx.compose.ui.platform.rememberNestedScrollInteropConnection
|
|||
import androidx.fragment.app.viewModels
|
||||
import com.tangem.core.ui.fragments.ComposeBottomSheetFragment
|
||||
import com.tangem.core.ui.res.TangemTheme
|
||||
import com.tangem.tap.common.analytics.Analytics
|
||||
import com.tangem.core.analytics.Analytics
|
||||
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.RenameWalletDialogContent
|
||||
|
|
|
|||
|
|
@ -10,16 +10,11 @@ class DisclaimerPrefStorage(
|
|||
private val preferences: SharedPreferences,
|
||||
) {
|
||||
|
||||
var hasTangemTosAccepted: Boolean
|
||||
get() = preferences.getBoolean(KEY_TANGEM_TOS, false)
|
||||
set(value) = preferences.edit { putBoolean(KEY_TANGEM_TOS, value) }
|
||||
fun accept(disclaimerKey: String) {
|
||||
preferences.edit { putBoolean(disclaimerKey, true) }
|
||||
}
|
||||
|
||||
var hasSaltPayTosAccepted: Boolean
|
||||
get() = preferences.getBoolean(KEY_SALT_PAY_TOS, false)
|
||||
set(value) = preferences.edit { putBoolean(KEY_SALT_PAY_TOS, value) }
|
||||
|
||||
companion object {
|
||||
private const val KEY_TANGEM_TOS = "tangem_tos_accepted"
|
||||
private const val KEY_SALT_PAY_TOS = "saltPay_tos_accepted"
|
||||
fun isAccepted(disclaimerKey: String): Boolean {
|
||||
return preferences.getBoolean(disclaimerKey, false)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,6 +6,8 @@ import com.tangem.domain.common.ScanResponse
|
|||
import com.tangem.tap.common.redux.AppState
|
||||
import com.tangem.tap.domain.TangemSdkManager
|
||||
import com.tangem.tap.domain.tokens.UserTokensRepository
|
||||
import com.tangem.tap.domain.userWalletList.UserWalletsListManager
|
||||
import com.tangem.tap.domain.walletStores.WalletStoresManager
|
||||
import com.tangem.tap.features.wallet.redux.WalletState
|
||||
import org.rekotlin.Store
|
||||
import javax.inject.Inject
|
||||
|
|
@ -22,6 +24,8 @@ class AppStateHolder @Inject constructor(){
|
|||
var mainStore: Store<AppState>? = null
|
||||
var tangemSdkManager: TangemSdkManager? = null
|
||||
var tangemSdk: TangemSdk? = null
|
||||
var walletStoresManager: WalletStoresManager? = null
|
||||
var userWalletsListManager: UserWalletsListManager? = null
|
||||
|
||||
fun getActualCard(): CardDTO? {
|
||||
return scanResponse?.card
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ class DerivationManagerImpl(
|
|||
}
|
||||
|
||||
scope.launch {
|
||||
val selectedWallet = appStateHolder.userWalletsListManager?.selectedUserWalletSync
|
||||
|
||||
val result = appStateHolder.tangemSdkManager?.derivePublicKeys(
|
||||
scanResponse.card.cardId,
|
||||
derivations,
|
||||
|
|
@ -108,6 +110,14 @@ class DerivationManagerImpl(
|
|||
val updatedScanResponse = scanResponse.copy(
|
||||
derivedKeys = updatedDerivedKeys,
|
||||
)
|
||||
if (selectedWallet != null) {
|
||||
val userWallet = selectedWallet.copy(
|
||||
scanResponse = updatedScanResponse,
|
||||
)
|
||||
|
||||
appStateHolder.userWalletsListManager?.save(userWallet, canOverride = true)
|
||||
appStateHolder.walletStoresManager?.fetch(userWallet, true)
|
||||
}
|
||||
appStateHolder.mainStore?.dispatchOnMain(GlobalAction.SaveScanResponse(updatedScanResponse))
|
||||
delay(DELAY_SDK_DIALOG_CLOSE)
|
||||
onSuccess(updatedScanResponse)
|
||||
|
|
@ -115,8 +125,7 @@ class DerivationManagerImpl(
|
|||
is CompletionResult.Failure -> {
|
||||
appStateHolder.mainStore?.dispatchDebugErrorNotification(
|
||||
TapError.CustomError(
|
||||
"Error adding " +
|
||||
"tokens",
|
||||
"Error derivation",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
android:id="@+id/nested_scroll"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginStart="16dp"
|
||||
|
|
@ -53,35 +54,83 @@
|
|||
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/guideline"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintGuide_percent="0.37" />
|
||||
|
||||
<View
|
||||
android:id="@+id/half_transparent_overlay"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="100dp"
|
||||
android:layout_height="140dp"
|
||||
android:background="@drawable/bg_half_transparent_overlay"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:lineSpacingExtra="5sp"
|
||||
android:text="@string/disclaimer_error_loading"
|
||||
android:textAlignment="center"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/btn_repeat"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_chainStyle="packed" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/btn_repeat"
|
||||
style="@style/OnboardingButton.Alternative"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/common_retry"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.5"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_error" />
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_accept"
|
||||
style="@style/TapButtonWithIcon"
|
||||
style="@style/TapButton"
|
||||
android:layout_width="0dp"
|
||||
android:layout_marginStart="7dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="@string/common_accept"
|
||||
app:icon="@drawable/ic_send"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline" />
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="btn_repeat, tv_error" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_loading"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="progress" />
|
||||
|
||||
<androidx.constraintlayout.widget.Group
|
||||
android:id="@+id/group_accept"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:constraint_referenced_ids="btn_accept, half_transparent_overlay" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -60,8 +60,7 @@ object Versions {
|
|||
// endregion Other libraries
|
||||
|
||||
// region Tangem
|
||||
const val tangemBlockchainSdk = "develop-142"
|
||||
// const val tangemBlockchainSdk = "0.0.1"
|
||||
const val tangemBlockchainSdk = "develop-151"
|
||||
|
||||
const val tangemCardSgk = "develop-179"
|
||||
// endregion Tangem
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue