Loading feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/FeatureFundingModule.kt +6 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import app.k9mail.feature.funding.googleplay.GooglePlayFundingManager import app.k9mail.feature.funding.googleplay.GooglePlayFundingNavigation import app.k9mail.feature.funding.googleplay.data.DataContract import app.k9mail.feature.funding.googleplay.data.GoogleBillingClient import app.k9mail.feature.funding.googleplay.data.mapper.BillingResultMapper import app.k9mail.feature.funding.googleplay.data.mapper.ProductDetailsMapper import app.k9mail.feature.funding.googleplay.domain.BillingManager import app.k9mail.feature.funding.googleplay.domain.ContributionIdProvider Loading @@ -23,10 +24,15 @@ val featureFundingModule = module { ProductDetailsMapper() } single<DataContract.Mapper.BillingResult> { BillingResultMapper() } single<DataContract.BillingClient> { GoogleBillingClient( context = get(), productMapper = get(), resultMapper = get(), productCache = InMemoryCache(), ) } Loading feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/DataContract.kt +10 −0 Original line number Diff line number Diff line package app.k9mail.feature.funding.googleplay.data import android.app.Activity import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError import app.k9mail.feature.funding.googleplay.domain.Outcome import app.k9mail.feature.funding.googleplay.domain.entity.Contribution import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution import com.android.billingclient.api.ProductDetails import com.android.billingclient.api.BillingResult as GoogleBillingResult interface DataContract { Loading @@ -15,6 +18,13 @@ interface DataContract { fun mapToOneTimeContribution(product: ProductDetails): OneTimeContribution fun mapToRecurringContribution(product: ProductDetails): RecurringContribution } interface BillingResult { fun <T> mapToOutcome( billingResult: GoogleBillingResult, transformSuccess: () -> T, ): Outcome<T, BillingError> } } interface BillingClient { Loading feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/GoogleBillingClient.kt +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import timber.log.Timber class GoogleBillingClient( private val context: Context, private val productMapper: DataContract.Mapper.Product, private val resultMapper: DataContract.Mapper.BillingResult, private val productCache: Cache<String, ProductDetails>, backgroundDispatcher: CoroutineContext = Dispatchers.IO, ) : DataContract.BillingClient, PurchasesUpdatedListener { Loading feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/mapper/BillingResultMapper.kt 0 → 100644 +46 −0 Original line number Diff line number Diff line package app.k9mail.feature.funding.googleplay.data.mapper import app.k9mail.feature.funding.googleplay.data.DataContract.Mapper import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError import app.k9mail.feature.funding.googleplay.domain.Outcome import com.android.billingclient.api.BillingClient.BillingResponseCode import com.android.billingclient.api.BillingResult class BillingResultMapper : Mapper.BillingResult { override fun <T> mapToOutcome( billingResult: BillingResult, transformSuccess: () -> T, ): Outcome<T, BillingError> { return when (billingResult.responseCode) { BillingResponseCode.OK -> { Outcome.success(transformSuccess()) } else -> { Outcome.failure(mapToBillingError(billingResult)) } } } private fun mapToBillingError(billingResult: BillingResult): BillingError { return when (billingResult.responseCode) { BillingResponseCode.SERVICE_DISCONNECTED, BillingResponseCode.SERVICE_UNAVAILABLE, BillingResponseCode.BILLING_UNAVAILABLE, BillingResponseCode.NETWORK_ERROR, -> BillingError.ServiceDisconnected(billingResult.debugMessage) BillingResponseCode.ITEM_ALREADY_OWNED, BillingResponseCode.ITEM_NOT_OWNED, BillingResponseCode.ITEM_UNAVAILABLE, -> BillingError.PurchaseFailed(billingResult.debugMessage) BillingResponseCode.USER_CANCELED -> BillingError.UserCancelled(billingResult.debugMessage) BillingResponseCode.DEVELOPER_ERROR -> BillingError.DeveloperError(billingResult.debugMessage) else -> BillingError.UnknownError(billingResult.debugMessage) } } } feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/domain/DomainContract.kt +12 −0 Original line number Diff line number Diff line Loading @@ -46,4 +46,16 @@ interface DomainContract { */ fun clear() } sealed interface BillingError { val message: String data class BillingServiceDisconnected( override val message: String, ) : BillingError data class BillingUnknownError( override val message: String, ) : BillingError } } Loading
feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/FeatureFundingModule.kt +6 −0 Original line number Diff line number Diff line Loading @@ -7,6 +7,7 @@ import app.k9mail.feature.funding.googleplay.GooglePlayFundingManager import app.k9mail.feature.funding.googleplay.GooglePlayFundingNavigation import app.k9mail.feature.funding.googleplay.data.DataContract import app.k9mail.feature.funding.googleplay.data.GoogleBillingClient import app.k9mail.feature.funding.googleplay.data.mapper.BillingResultMapper import app.k9mail.feature.funding.googleplay.data.mapper.ProductDetailsMapper import app.k9mail.feature.funding.googleplay.domain.BillingManager import app.k9mail.feature.funding.googleplay.domain.ContributionIdProvider Loading @@ -23,10 +24,15 @@ val featureFundingModule = module { ProductDetailsMapper() } single<DataContract.Mapper.BillingResult> { BillingResultMapper() } single<DataContract.BillingClient> { GoogleBillingClient( context = get(), productMapper = get(), resultMapper = get(), productCache = InMemoryCache(), ) } Loading
feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/DataContract.kt +10 −0 Original line number Diff line number Diff line package app.k9mail.feature.funding.googleplay.data import android.app.Activity import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError import app.k9mail.feature.funding.googleplay.domain.Outcome import app.k9mail.feature.funding.googleplay.domain.entity.Contribution import app.k9mail.feature.funding.googleplay.domain.entity.OneTimeContribution import app.k9mail.feature.funding.googleplay.domain.entity.RecurringContribution import com.android.billingclient.api.ProductDetails import com.android.billingclient.api.BillingResult as GoogleBillingResult interface DataContract { Loading @@ -15,6 +18,13 @@ interface DataContract { fun mapToOneTimeContribution(product: ProductDetails): OneTimeContribution fun mapToRecurringContribution(product: ProductDetails): RecurringContribution } interface BillingResult { fun <T> mapToOutcome( billingResult: GoogleBillingResult, transformSuccess: () -> T, ): Outcome<T, BillingError> } } interface BillingClient { Loading
feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/GoogleBillingClient.kt +1 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ import timber.log.Timber class GoogleBillingClient( private val context: Context, private val productMapper: DataContract.Mapper.Product, private val resultMapper: DataContract.Mapper.BillingResult, private val productCache: Cache<String, ProductDetails>, backgroundDispatcher: CoroutineContext = Dispatchers.IO, ) : DataContract.BillingClient, PurchasesUpdatedListener { Loading
feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/data/mapper/BillingResultMapper.kt 0 → 100644 +46 −0 Original line number Diff line number Diff line package app.k9mail.feature.funding.googleplay.data.mapper import app.k9mail.feature.funding.googleplay.data.DataContract.Mapper import app.k9mail.feature.funding.googleplay.domain.DomainContract.BillingError import app.k9mail.feature.funding.googleplay.domain.Outcome import com.android.billingclient.api.BillingClient.BillingResponseCode import com.android.billingclient.api.BillingResult class BillingResultMapper : Mapper.BillingResult { override fun <T> mapToOutcome( billingResult: BillingResult, transformSuccess: () -> T, ): Outcome<T, BillingError> { return when (billingResult.responseCode) { BillingResponseCode.OK -> { Outcome.success(transformSuccess()) } else -> { Outcome.failure(mapToBillingError(billingResult)) } } } private fun mapToBillingError(billingResult: BillingResult): BillingError { return when (billingResult.responseCode) { BillingResponseCode.SERVICE_DISCONNECTED, BillingResponseCode.SERVICE_UNAVAILABLE, BillingResponseCode.BILLING_UNAVAILABLE, BillingResponseCode.NETWORK_ERROR, -> BillingError.ServiceDisconnected(billingResult.debugMessage) BillingResponseCode.ITEM_ALREADY_OWNED, BillingResponseCode.ITEM_NOT_OWNED, BillingResponseCode.ITEM_UNAVAILABLE, -> BillingError.PurchaseFailed(billingResult.debugMessage) BillingResponseCode.USER_CANCELED -> BillingError.UserCancelled(billingResult.debugMessage) BillingResponseCode.DEVELOPER_ERROR -> BillingError.DeveloperError(billingResult.debugMessage) else -> BillingError.UnknownError(billingResult.debugMessage) } } }
feature/funding/googleplay/src/main/kotlin/app/k9mail/feature/funding/googleplay/domain/DomainContract.kt +12 −0 Original line number Diff line number Diff line Loading @@ -46,4 +46,16 @@ interface DomainContract { */ fun clear() } sealed interface BillingError { val message: String data class BillingServiceDisconnected( override val message: String, ) : BillingError data class BillingUnknownError( override val message: String, ) : BillingError } }