Updated on 2026-08-14

This commit is contained in:
Tangem 2023-07-22 19:55:33 +03:00
parent b4aac690c5
commit 1169ea6d84
6 changed files with 72 additions and 38 deletions

View file

@ -109,6 +109,7 @@ class WalletFragment : Fragment(R.layout.fragment_wallet), SafeStoreSubscriber<W
val inflater = TransitionInflater.from(requireContext())
enterTransition = inflater.inflateTransition(R.transition.slide_right)
exitTransition = inflater.inflateTransition(R.transition.fade)
learn2earnViewModel.onMainScreenCreated()
}
override fun onStart() {

View file

@ -29,7 +29,7 @@ import timber.log.Timber
/**
[REDACTED_AUTHOR]
*/
@Suppress("LongParameterList")
@Suppress("LongParameterList", "LargeClass")
internal class DefaultLearn2earnInteractor(
private val featureToggleManager: Learn2earnFeatureToggleManager,
private val repository: Learn2earnRepository,
@ -43,19 +43,22 @@ internal class DefaultLearn2earnInteractor(
override var webViewResultHandler: WebViewResultHandler? = null
private val promoUserData: PromoUserData
get() = repository.getUserData()
private lateinit var promotion: Promotion
private val scope = CoroutineScope(Job() + dispatchers.io + FeatureCoroutineExceptionHandler.create("mainScope"))
private val isTangemWalletFlow = MutableStateFlow(false)
private var isTangemWalletFlowJob: Job? = null
private var isTangemWalletFlowSync = false
private var isTangemWalletSync = false
private val webViewUriBuilder: WebViewUriBuilder by lazy {
WebViewUriBuilder(
authCredentialsProvider = dependencyProvider.getWebViewAuthCredentialsProvider(),
localeLanguageProvider = dependencyProvider.getLocaleProvider(),
promoCodeProvider = { repository.getUserData().promoCode },
promoCodeProvider = { promoUserData.promoCode },
)
}
@ -70,12 +73,13 @@ internal class DefaultLearn2earnInteractor(
override fun getIsTangemWalletFlow(): Flow<Boolean> = isTangemWalletFlow
override fun isUserHadPromoCode(): Boolean {
return repository.getUserData().promoCode != null
return promoUserData.promoCode != null
}
override suspend fun validateUserWallet(): Result<Unit> {
val promoCode = repository.getUserData().promoCode
val promoCode = promoUserData.promoCode
val userWalletId = userWalletManager.getWalletId()
if (userWalletId.isEmpty()) return Result.failure(PromotionError.EmptyUserWalletId)
val domainError = if (promoCode == null) {
repository.validate(userWalletId).error
@ -92,14 +96,13 @@ internal class DefaultLearn2earnInteractor(
}
override fun isUserRegisteredInPromotion(): Boolean {
return repository.getUserData().isRegisteredInPromotion
return promoUserData.isRegisteredInPromotion
}
override fun getAwardAmount(): Int = try {
val promoCode = repository.getUserData().promoCode
promotion.getPromotionInfo().getData(promoCode).award.toInt()
promotion.getPromotionInfo().getCardData().award.toInt()
} catch (ex: NullPointerException) {
Timber.e(ex)
Timber.w(ex)
0
}
@ -114,7 +117,7 @@ internal class DefaultLearn2earnInteractor(
?: return Result.failure(PromotionError.UnknownError("Currency for award is null"))
val walletId = userWalletManager.getWalletId()
val promoCode = repository.getUserData().promoCode
val promoCode = promoUserData.promoCode
val domainError = if (promoCode == null) {
requestAward(walletId, awardCurrency)
@ -199,11 +202,11 @@ internal class DefaultLearn2earnInteractor(
}
override fun buildUriForNewUser(): Uri {
return webViewUriBuilder.buildUriForNewUser(repository.getUserData().isLearningStageFinished)
return webViewUriBuilder.buildUriForNewUser(promoUserData.isLearningStageFinished)
}
override fun buildUriForOldUser(): Uri {
return webViewUriBuilder.buildUriForOldUser(repository.getUserData().isLearningStageFinished)
return webViewUriBuilder.buildUriForOldUser(promoUserData.isLearningStageFinished)
}
override fun getBasicAuthHeaders(): ArrayList<String> {
@ -251,8 +254,8 @@ internal class DefaultLearn2earnInteractor(
val isActive = when {
demoModeDatasource.isDemoModeActive -> false
!featureToggleManager.isLearn2earnEnabled -> false
repository.getUserData().isAlreadyReceivedAward -> false
else -> !promotion.isError()
promoUserData.isAlreadyReceivedAward -> false
else -> promotion.isReadyToUse()
}
return isActive
@ -267,10 +270,18 @@ internal class DefaultLearn2earnInteractor(
}
override fun isPromotionActiveOnMain(): Boolean {
return when {
!isPromotionActive() -> false
!isTangemWalletFlowSync -> false
else -> promotion.getPromotionInfo().oldCard.status == PromotionInfoResponse.Status.ACTIVE
if (!isPromotionActive() || !isTangemWalletSync) return false
val promotionInfo = promotion.getPromotionInfo()
return if (isUseLogicForOldCards()) {
promotionInfo.oldCard.status == PromotionInfoResponse.Status.ACTIVE
} else {
when (promotionInfo.newCard.status) {
PromotionInfoResponse.Status.PENDING -> false
PromotionInfoResponse.Status.ACTIVE -> true
// disable promotion for a new user only if they have received an award
PromotionInfoResponse.Status.FINISHED -> !promoUserData.isAlreadyReceivedAward
}
}
}
@ -325,25 +336,35 @@ internal class DefaultLearn2earnInteractor(
)
}
private fun updateUserData(updateBlock: (PromoUserData) -> PromoUserData): PromoUserData {
return updateBlock(repository.getUserData()).apply {
repository.updateUserData(this)
}
}
private fun subscribeToCardTypeResolverFlow() {
if (isTangemWalletFlowJob == null || isTangemWalletFlowJob?.isCancelled == true) {
isTangemWalletFlowJob = dependencyProvider.getCardTypeResolverFlow()
.onEach {
isTangemWalletFlowSync = it?.isTangemWallet() ?: false
isTangemWalletFlow.emit(isTangemWalletFlowSync)
val isTangemWallet = it?.isTangemWallet() ?: false
isTangemWalletSync = isTangemWallet
isTangemWalletFlow.emit(isTangemWallet)
}
.launchIn(scope)
}
}
private fun Promotion.PromotionInfo.getData(promoCode: String?): PromotionInfoResponse.Data {
return if (promoCode == null) {
// region Utils
private fun updateUserData(updateBlock: (PromoUserData) -> PromoUserData): PromoUserData {
return updateBlock(promoUserData).apply {
repository.updateUserData(this)
}
}
private fun isUseLogicForOldCards(): Boolean {
return promoUserData.promoCode == null
}
private fun Promotion.isReadyToUse(): Boolean {
return info != null
}
private fun Promotion.PromotionInfo.getCardData(): PromotionInfoResponse.Data {
return if (isUseLogicForOldCards()) {
oldCard
} else {
newCard
@ -360,4 +381,5 @@ internal class DefaultLearn2earnInteractor(
WebViewResult.Empty -> WebViewAction.PROCEED
}
}
// endregion Utils
}

View file

@ -13,8 +13,6 @@ internal data class Promotion(
@Throws(NullPointerException::class)
fun getPromotionInfo(): PromotionInfo = info!!
fun isError(): Boolean = error != null
data class PromotionInfo(
val newCard: PromotionInfoResponse.Data,
val oldCard: PromotionInfoResponse.Data,

View file

@ -20,6 +20,7 @@ sealed class PromotionError(val code: Int, val description: String) : Throwable(
class ProgramWasEnd(code: Int, description: String) : PromotionError(code, description)
class UnknownError(description: String) : PromotionError(code = -1, description)
object EmptyUserWalletId : PromotionError(code = -1, "UserWalletId is empty")
}
@Suppress("MagicNumber")

View file

@ -64,6 +64,10 @@ class Learn2earnViewModel @Inject constructor(
}
}
fun onMainScreenCreated() {
updateMainScreenViews()
}
fun onMainScreenRefreshed() {
updateMainScreenViews()
}
@ -113,7 +117,9 @@ class Learn2earnViewModel @Inject constructor(
-> {
updateUi { uiState.updateViewsVisibility(isVisible = false) }
}
is PromotionError.CodeWasNotAppliedInShop -> {
is PromotionError.CodeWasNotAppliedInShop,
is PromotionError.EmptyUserWalletId,
-> {
updateUi { uiState.updateGetBonusVisibility(isVisible = false) }
}
is PromotionError.CodeNotFound,
@ -167,9 +173,13 @@ class Learn2earnViewModel @Inject constructor(
},
onFailure = {
val errorDialog = createErrorDialog(it.toDomainError())
updateUi {
uiState.updateProgress(showProgress = false)
.showDialog(errorDialog)
if (errorDialog == null) {
updateUi { uiState.updateProgress(showProgress = false) }
} else {
updateUi {
uiState.updateProgress(showProgress = false)
.showDialog(errorDialog)
}
}
},
)
@ -178,8 +188,9 @@ class Learn2earnViewModel @Inject constructor(
updateUi { uiState.updateProgress(showProgress = false) }
if (exception is UserCancelledException) return@launch
val errorDialog = createErrorDialog(exception.toDomainError())
updateUi { uiState.showDialog(errorDialog) }
createErrorDialog(exception.toDomainError())?.let {
updateUi { uiState.showDialog(it) }
}
}
}
}
@ -192,7 +203,7 @@ class Learn2earnViewModel @Inject constructor(
}
}
private fun createErrorDialog(error: PromotionError): MainScreenState.Dialog {
private fun createErrorDialog(error: PromotionError): MainScreenState.Dialog? {
return when (error) {
is PromotionError.CodeWasNotAppliedInShop -> {
val onHideDialog = { uiState = uiState.hideDialog() }
@ -231,6 +242,7 @@ class Learn2earnViewModel @Inject constructor(
onDismissRequest = onHideDialog,
)
}
is PromotionError.EmptyUserWalletId -> null
}
}

View file

@ -19,7 +19,7 @@ interface UserWalletManager {
fun getNativeTokenForNetwork(networkId: String): Currency
/**
* Returns user walletId
* Returns user walletId or empty string
*/
fun getWalletId(): String