Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-20 15:57:36 +03:00
parent 7daafed11b
commit f6ae66e7b7
13 changed files with 82 additions and 38 deletions

View file

@ -2,6 +2,8 @@ package com.tangem.tap.proxy.di
import androidx.compose.ui.text.intl.Locale
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.domain.common.CardTypesResolver
import com.tangem.domain.common.util.cardTypesResolver
import com.tangem.feature.learn2earn.domain.api.Learn2earnDependencyProvider
import com.tangem.lib.crypto.DerivationManager
import com.tangem.lib.crypto.TransactionManager
@ -56,6 +58,10 @@ class ProxyModule {
@Singleton
fun provideLear2earnDependencies(appStateHolder: AppStateHolder): Learn2earnDependencyProvider {
return object : Learn2earnDependencyProvider {
override fun getCardTypeResolver(): CardTypesResolver? {
return appStateHolder.userWalletsListManager?.selectedUserWalletSync?.scanResponse?.cardTypesResolver
}
override fun getLocaleProvider(): () -> String = { Locale.current.language }
override fun getWebViewAuthCredentialsProvider(): () -> String? = {

View file

@ -163,10 +163,10 @@
<string name="key_invalidated_warning_description">Вы обновили данные биометрии, отсканируйте свою карту для входа</string>
<string name="main_get_bonus_subtitle">Вы успешно прошли все уроки и теперь можете получить 1INCH токены</string>
<plurals name="main_learn_subtitle">
<item quantity="one">Пройдите 3 урока и получите %d 1INCH токен на свой кошелек</item>
<item quantity="few">Пройдите 3 урока и получите %d 1INCH токена на свой кошелек</item>
<item quantity="many">Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек</item>
<item quantity="other">Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек</item>
<item quantity="one">Пройдите 3 урока и получите %d 1INCH токен на свой кошелек</item>
<item quantity="few">Пройдите 3 урока и получите %d 1INCH токена на свой кошелек</item>
<item quantity="many">Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек</item>
<item quantity="other">Пройдите 3 урока и получите %d 1INCH токенов на свой кошелек</item>
</plurals>
<string name="main_manage_tokens">Управление токенами</string>
<string name="main_no_backup_warning_subtitle">Чтобы защитить свои активы, мы советуем вам выполнить эту процедуру</string>

View file

@ -161,8 +161,8 @@
<string name="key_invalidated_warning_description">You have updated biometrics, scan your card to enter</string>
<string name="main_get_bonus_subtitle">You have completed all of the lessons, and are now eligible to receive your 1INCH tokens</string>
<plurals name="main_learn_subtitle">
<item quantity="one">Complete three lessons and receive %d 1INCH token to your wallet</item>
<item quantity="other">Complete three lessons and receive %d 1INCH tokens to your wallet</item>
<item quantity="one">Complete three lessons and receive %d 1INCH token to your wallet</item>
<item quantity="other">Complete three lessons and receive %d 1INCH tokens to your wallet</item>
</plurals>
<string name="main_manage_tokens">Manage tokens</string>
<string name="main_no_backup_warning_subtitle">To protect your assets, we advise you to carry out this procedure</string>

View file

@ -10,6 +10,7 @@ plugins {
dependencies {
/** Core modules */
implementation(project(":common"))
implementation(project(":domain:legacy"))
implementation(project(":core:analytics"))
implementation(project(":core:featuretoggles"))
implementation(project(":core:datasource"))

View file

@ -121,6 +121,7 @@ internal class DefaultLearn2earnRepository(
promoCode = null,
isRegisteredInPromotion = false,
isAlreadyReceivedAward = false,
isLearningStageFinished = false,
)
private companion object {

View file

@ -5,6 +5,7 @@ package com.tangem.feature.learn2earn.data.models
*/
data class PromoUserData(
val promoCode: String?,
val isLearningStageFinished: Boolean,
val isRegisteredInPromotion: Boolean,
val isAlreadyReceivedAward: Boolean,
)

View file

@ -3,6 +3,8 @@ package com.tangem.feature.learn2earn.domain
import android.net.Uri
import com.tangem.core.analytics.api.AnalyticsEventHandler
import com.tangem.datasource.api.promotion.models.PromotionInfoResponse
import com.tangem.feature.learn2earn.analytics.AnalyticsParam
import com.tangem.feature.learn2earn.analytics.Learn2earnEvents.*
import com.tangem.feature.learn2earn.data.api.Learn2earnRepository
import com.tangem.feature.learn2earn.data.models.PromoUserData
import com.tangem.feature.learn2earn.data.toggles.Learn2earnFeatureToggleManager
@ -22,8 +24,8 @@ internal class DefaultLearn2earnInteractor(
private val repository: Learn2earnRepository,
private val userWalletManager: UserWalletManager,
private val derivationManager: DerivationManager,
private val analyticsEventHandler: AnalyticsEventHandler,
dependencyProvider: Learn2earnDependencyProvider,
private val analytics: AnalyticsEventHandler,
private val dependencyProvider: Learn2earnDependencyProvider,
) : Learn2earnInteractor {
override var webViewResultHandler: WebViewResultHandler? = null
@ -171,11 +173,11 @@ internal class DefaultLearn2earnInteractor(
}
override fun buildUriForNewUser(): Uri {
return webViewUriBuilder.buildUriForNewUser()
return webViewUriBuilder.buildUriForNewUser(repository.getUserData().isLearningStageFinished)
}
override fun buildUriForOldUser(): Uri {
return webViewUriBuilder.buildUriForOldUser()
return webViewUriBuilder.buildUriForOldUser(repository.getUserData().isLearningStageFinished)
}
override fun getBasicAuthHeaders(): ArrayList<String> {
@ -185,11 +187,22 @@ internal class DefaultLearn2earnInteractor(
override fun handleRedirect(uri: Uri): WebViewAction {
val result = webViewUriParser.parse(uri)
when (result) {
is WebViewResult.PromoCode -> {
is WebViewResult.NewUserLearningFinished -> {
analytics.send(PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.New()))
updateUserData {
it.copy(
promoCode = result.promoCode,
isRegisteredInPromotion = true,
isLearningStageFinished = true,
)
}
}
is WebViewResult.OldUserLearningFinished -> {
analytics.send(PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.Old()))
updateUserData {
it.copy(
promoCode = null,
isLearningStageFinished = true,
)
}
}
@ -197,7 +210,7 @@ internal class DefaultLearn2earnInteractor(
updateUserData { it.copy(isRegisteredInPromotion = true) }
}
is WebViewResult.Learn2earnAnalyticsEvent -> {
analyticsEventHandler.send(result.event)
analytics.send(result.event)
}
WebViewResult.Empty -> Unit
}
@ -222,6 +235,8 @@ internal class DefaultLearn2earnInteractor(
}
override fun isPromotionActiveOnMain(): Boolean {
if (dependencyProvider.getCardTypeResolver()?.isTangemWallet() != true) return false
val isActiveStatus = promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE
return isPromotionActive() && isActiveStatus
}
@ -293,10 +308,12 @@ internal class DefaultLearn2earnInteractor(
private fun WebViewResult.toWebViewAction(): WebViewAction {
return when (this) {
WebViewResult.Empty -> WebViewAction.PROCEED
is WebViewResult.NewUserLearningFinished,
WebViewResult.OldUserLearningFinished,
is WebViewResult.Learn2earnAnalyticsEvent,
-> WebViewAction.NOTHING
WebViewResult.ReadyForAward -> WebViewAction.FINISH_SESSION
is WebViewResult.Learn2earnAnalyticsEvent -> WebViewAction.NOTHING
is WebViewResult.PromoCode -> WebViewAction.NOTHING
WebViewResult.Empty -> WebViewAction.PROCEED
}
}
}

View file

@ -12,8 +12,8 @@ internal class WebViewUriBuilder(
private val promoCodeProvider: () -> String?,
) {
fun buildUriForNewUser(): Uri {
val builder = makeWebViewUriBuilder()
fun buildUriForNewUser(learningIsFinished: Boolean): Uri {
val builder = makeWebViewUriBuilder(learningIsFinished)
.appendQueryParameter("type", QUERY_NEW_CARD)
promoCodeProvider.invoke()?.let {
@ -23,9 +23,9 @@ internal class WebViewUriBuilder(
return builder.build()
}
fun buildUriForOldUser(): Uri {
val builder = makeWebViewUriBuilder()
.appendQueryParameter("type", QUERY_EXISTED_CARD)
fun buildUriForOldUser(learningIsFinished: Boolean): Uri {
val builder = makeWebViewUriBuilder(learningIsFinished)
.appendQueryParameter("type", QUERY_EXISTING_CARD)
return builder.build()
}
@ -39,7 +39,7 @@ internal class WebViewUriBuilder(
}
}
private fun makeWebViewUriBuilder(): Uri.Builder = Uri.Builder().apply {
private fun makeWebViewUriBuilder(learningIsFinished: Boolean): Uri.Builder = Uri.Builder().apply {
scheme(SCHEME)
if (BuildConfig.DEBUG) {
authority(DEV_BASE_URL)
@ -48,6 +48,7 @@ internal class WebViewUriBuilder(
}
appendPath(getLocaleLanguage(localeLanguageProvider.invoke()))
appendPath(PATH_PROMOTION)
appendQueryParameter(QUERY_FINISHED, learningIsFinished.toString())
}
// TODO: locale: This can be used by another feature. Move it to the appropriate location
@ -66,7 +67,8 @@ internal class WebViewUriBuilder(
const val PATH_PROMOTION = "promotion"
const val QUERY_NEW_CARD = "new-card"
const val QUERY_EXISTED_CARD = "existed-card"
const val QUERY_EXISTING_CARD = "existing-card"
const val QUERY_FINISHED = "finished"
const val DEV_BASE_URL = "devweb.tangem.com"

View file

@ -1,7 +1,6 @@
package com.tangem.feature.learn2earn.domain
import android.net.Uri
import com.tangem.feature.learn2earn.analytics.AnalyticsParam
import com.tangem.feature.learn2earn.analytics.Learn2earnEvents
import com.tangem.feature.learn2earn.analytics.Learn2earnEvents.PromoScreen
import com.tangem.feature.learn2earn.domain.api.WebViewResult
@ -22,14 +21,17 @@ internal class WebViewUriParser(
WebViewResult.Learn2earnAnalyticsEvent(event)
}
}
isPromoCodeRedirect(uri) -> {
isSuccessNewUserRedirect(uri) -> {
val promoCode = extractPromoCode(uri)
if (promoCode == null) {
WebViewResult.Empty
} else {
WebViewResult.PromoCode(promoCode)
WebViewResult.NewUserLearningFinished(promoCode)
}
}
isSuccessOldUserRedirect(uri) -> {
WebViewResult.OldUserLearningFinished
}
isReadyForAwardRedirect(uri) -> {
WebViewResult.ReadyForAward
}
@ -40,13 +42,18 @@ internal class WebViewUriParser(
return uri.lastPathSegment == PATH_READY_FOR_AWARD
}
private fun isPromoCodeRedirect(uri: Uri): Boolean {
return uri.lastPathSegment == PATH_PROMO_CODE_CREATED &&
private fun isSuccessNewUserRedirect(uri: Uri): Boolean {
return uri.lastPathSegment == PATH_LEARNING_SUCCESS &&
uri.queryParameterNames.contains(QUERY_PROMO_CODE)
}
private fun isSuccessOldUserRedirect(uri: Uri): Boolean {
return uri.lastPathSegment == PATH_LEARNING_SUCCESS &&
!uri.queryParameterNames.contains(QUERY_PROMO_CODE)
}
private fun extractPromoCode(uri: Uri): String? {
return if (isPromoCodeRedirect(uri)) {
return if (isSuccessNewUserRedirect(uri)) {
uri.getQueryParameter(QUERY_PROMO_CODE)
} else {
null
@ -68,16 +75,14 @@ internal class WebViewUriParser(
val analyticsEvent = when (event) {
EVENT_PROMO_BUY -> PromoScreen.ButtonBuy()
EVENT_PROMO_SUCCESS_NEW_USER -> PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.New())
EVENT_PROMO_SUCCESS_OLD_USER -> PromoScreen.SuccessScreenOpened(AnalyticsParam.ClientType.Old())
else -> null
}
return analyticsEvent
}
private companion object {
const val PATH_PROMO_CODE_CREATED = "code-created"
const val PATH_READY_FOR_AWARD = "ready-for-existed-card-award"
const val PATH_LEARNING_SUCCESS = "success"
const val PATH_READY_FOR_AWARD = "ready-for-existing-card-award"
const val PATH_ANALYTICS = "analytics"
const val QUERY_PROMO_CODE = "code"
@ -85,7 +90,5 @@ internal class WebViewUriParser(
const val QUERY_PROGRAM_NAME = "programName"
const val EVENT_PROMO_BUY = "promotion-buy"
const val EVENT_PROMO_SUCCESS_NEW_USER = "promotion-success-new-user"
const val EVENT_PROMO_SUCCESS_OLD_USER = "promotion-success-old-user"
}
}

View file

@ -1,5 +1,7 @@
package com.tangem.feature.learn2earn.domain.api
import com.tangem.domain.common.CardTypesResolver
/**
* Interface, a wrapper that allows us to get values from the AppStateHolder located in the app module
*
@ -7,6 +9,8 @@ package com.tangem.feature.learn2earn.domain.api
*/
interface Learn2earnDependencyProvider {
fun getCardTypeResolver(): CardTypesResolver?
fun getLocaleProvider(): () -> String
fun getWebViewAuthCredentialsProvider(): () -> String?

View file

@ -12,8 +12,14 @@ interface WebViewResultHandler {
}
sealed class WebViewResult {
object Empty : WebViewResult()
data class PromoCode(val promoCode: String) : WebViewResult()
data class NewUserLearningFinished(val promoCode: String?) : WebViewResult()
object OldUserLearningFinished : WebViewResult()
object ReadyForAward : WebViewResult()
data class Learn2earnAnalyticsEvent(val event: AnalyticsEvent) : WebViewResult()
}

View file

@ -51,7 +51,7 @@ internal class Learn2earnDomainModule {
repository = repository,
userWalletManager = userWalletManager,
derivationManager = derivationManager,
analyticsEventHandler = analyticsEventHandler,
analytics = analyticsEventHandler,
dependencyProvider = dependencyProvider,
)
}

View file

@ -220,7 +220,7 @@ class Learn2earnViewModel @Inject constructor(
interactor.webViewResultHandler = object : WebViewResultHandler {
override fun handleResult(result: WebViewResult) {
when (result) {
is WebViewResult.PromoCode -> {
is WebViewResult.NewUserLearningFinished -> {
interactor.webViewResultHandler = null
}
WebViewResult.ReadyForAward -> {
@ -228,7 +228,10 @@ class Learn2earnViewModel @Inject constructor(
updateMainScreenViews()
requestAward()
}
WebViewResult.Empty, is WebViewResult.Learn2earnAnalyticsEvent -> Unit
is WebViewResult.OldUserLearningFinished,
is WebViewResult.Learn2earnAnalyticsEvent,
WebViewResult.Empty,
-> Unit
}
}
}