Updated on 2026-08-14

This commit is contained in:
Tangem 2026-02-03 18:18:37 +05:00
parent f3fdcb3e3f
commit 03c65b35cf
7 changed files with 107 additions and 103 deletions

View file

@ -0,0 +1,50 @@
package com.tangem.tap
import android.app.Activity
import com.google.android.gms.tasks.Task
import com.google.android.play.core.review.ReviewInfo
import com.google.android.play.core.review.ReviewManagerFactory
import com.tangem.core.navigation.review.ReviewManager
import timber.log.Timber
import com.google.android.play.core.review.ReviewManager as GReviewManager
/**
* Implementation of [ReviewManager] for Google Play Store.
*/
internal class GoogleReviewManager : ReviewManager {
override fun request(onDismissClick: () -> Unit) {
foregroundActivityObserver.withForegroundActivity { activity ->
val reviewManager = ReviewManagerFactory.create(activity)
val requestTask = reviewManager.requestReviewFlow()
requestTask
.addOnCompleteListener { task ->
handleOnCompleteRequestTask(
reviewManager = reviewManager,
activity = activity,
task = task,
onDismissClick = onDismissClick,
)
}
.addOnFailureListener(Timber::e)
}
}
private fun handleOnCompleteRequestTask(
reviewManager: GReviewManager,
activity: Activity,
task: Task<ReviewInfo>,
onDismissClick: () -> Unit,
) {
if (task.isSuccessful) {
val reviewFlow = reviewManager.launchReviewFlow(activity, task.result)
reviewFlow
.addOnCompleteListener { resultReviewTask ->
if (!resultReviewTask.isSuccessful) onDismissClick()
}
.addOnFailureListener(Timber::e)
} else {
Timber.e(task.exception)
}
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.tap.di
import com.tangem.core.navigation.review.ReviewManager
import com.tangem.tap.GoogleReviewManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal class GoogleReviewManagerModule {
@Singleton
@Provides
fun provideGoogleReviewManager(): ReviewManager {
return GoogleReviewManager()
}
}

View file

@ -0,0 +1,20 @@
package com.tangem.tap.di
import com.tangem.core.navigation.review.DummyReviewManager
import com.tangem.core.navigation.review.ReviewManager
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
@Module
@InstallIn(SingletonComponent::class)
internal class HuaweiReviewManagerModule {
@Provides
@Singleton
fun provideHuaweiReviewManager(): ReviewManager {
return DummyReviewManager()
}
}

View file

@ -0,0 +1,5 @@
package com.tangem.core.navigation.review
class DummyReviewManager : ReviewManager {
override fun request(onDismissClick: () -> Unit) = Unit
}

View file

@ -0,0 +1,12 @@
package com.tangem.core.navigation.review
/**
* Interface to manage in-app review requests.
*/
interface ReviewManager {
/**
* Requests an in-app review flow.
*/
fun request(onDismissClick: () -> Unit)
}

View file

@ -1,56 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.domain
import arrow.core.Either
import arrow.core.raise.either
import arrow.core.raise.ensure
import com.tangem.common.CompletionResult
import com.tangem.common.core.TangemSdkError
import com.tangem.core.analytics.models.AnalyticsParam
import com.tangem.domain.card.ScanCardProcessor
import com.tangem.domain.wallets.builder.ColdUserWalletBuilder
import com.tangem.domain.models.wallet.UserWalletId
import com.tangem.domain.wallets.usecase.SaveWalletUseCase
import javax.inject.Inject
internal class ScanCardToUnlockWalletClickHandler @Inject constructor(
private val scanCardProcessor: ScanCardProcessor,
private val saveWalletUseCase: SaveWalletUseCase,
private val coldUserWalletBuilderFactory: ColdUserWalletBuilder.Factory,
) {
private var scanFailsCounter = 0
suspend operator fun invoke(walletId: UserWalletId): Either<ScanCardToUnlockWalletError, Unit> {
return either {
when (val result = scanCardProcessor.scan(analyticsSource = AnalyticsParam.ScreensSources.SignIn)) {
is CompletionResult.Failure -> {
if (result.error is TangemSdkError.UserCancelled) {
scanFailsCounter++
ensure(scanFailsCounter < 2) { ScanCardToUnlockWalletError.ManyScanFails }
}
}
is CompletionResult.Success -> {
scanFailsCounter = 0
// If card's public key is null then user wallet will be null
val scannedWallet = coldUserWalletBuilderFactory.create(scanResponse = result.data).build()
ensure(walletId == scannedWallet?.walletId) {
ScanCardToUnlockWalletError.WrongCardIsScanned
}
if (scannedWallet != null) {
saveWalletUseCase(userWallet = scannedWallet, canOverride = true)
}
}
}
}
}
}
internal sealed class ScanCardToUnlockWalletError {
object WrongCardIsScanned : ScanCardToUnlockWalletError()
object ManyScanFails : ScanCardToUnlockWalletError()
}

View file

@ -1,47 +0,0 @@
package com.tangem.feature.wallet.presentation.wallet.ui.utils
import android.app.Activity
import android.content.Context
import com.google.android.gms.tasks.Task
import com.google.android.play.core.review.ReviewInfo
import com.google.android.play.core.review.ReviewManager
import com.google.android.play.core.review.ReviewManagerFactory
import com.tangem.core.ui.utils.findActivity
import timber.log.Timber
internal object ReviewManagerRequester {
fun request(context: Context, onDismissClick: () -> Unit) {
val reviewManager = ReviewManagerFactory.create(context)
val requestTask = reviewManager.requestReviewFlow()
requestTask
.addOnCompleteListener {
handleOnCompleteRequestTask(
reviewManager = reviewManager,
activity = context.findActivity(),
task = it,
onDismissClick = onDismissClick,
)
}
.addOnFailureListener(Timber::e)
}
private fun handleOnCompleteRequestTask(
reviewManager: ReviewManager,
activity: Activity,
task: Task<ReviewInfo>,
onDismissClick: () -> Unit,
) {
if (task.isSuccessful) {
val reviewFlow = reviewManager.launchReviewFlow(activity, task.result)
reviewFlow
.addOnCompleteListener { resultReviewTask ->
if (!resultReviewTask.isSuccessful) onDismissClick()
}
.addOnFailureListener(Timber::e)
} else {
Timber.e(task.exception)
}
}
}