Skip to content

Commit

Permalink
Change contribution views to react on purchase and contribution error…
Browse files Browse the repository at this point in the history
…s along with nicer UI
  • Loading branch information
wmontwe committed Oct 21, 2024
1 parent b180cc7 commit ce1434b
Show file tree
Hide file tree
Showing 22 changed files with 642 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
import app.k9mail.feature.funding.googleplay.domain.DomainContract
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State

@Composable
Expand All @@ -13,9 +14,12 @@ fun ContributionContentPreview() {
PreviewWithTheme {
ContributionContent(
state = State(
recurringContributions = FakeData.recurringContributions,
oneTimeContributions = FakeData.oneTimeContributions,
selectedContribution = FakeData.recurringContributions.first(),
listState = ContributionListState(
recurringContributions = FakeData.recurringContributions,
oneTimeContributions = FakeData.oneTimeContributions,
selectedContribution = FakeData.recurringContributions.first(),
isLoading = false,
),
),
onEvent = {},
contentPadding = PaddingValues(),
Expand All @@ -28,7 +32,44 @@ fun ContributionContentPreview() {
fun ContributionContentEmptyPreview() {
PreviewWithTheme {
ContributionContent(
state = State(),
state = State(
listState = ContributionListState(
isLoading = false,
),
),
onEvent = {},
contentPadding = PaddingValues(),
)
}
}

@Composable
@Preview(showBackground = true)
fun ContributionContentLoadingPreview() {
PreviewWithTheme {
ContributionContent(
state = State(
listState = ContributionListState(
isLoading = true,
),
),
onEvent = {},
contentPadding = PaddingValues(),
)
}
}

@Composable
@Preview(showBackground = true)
fun ContributionContentListErrorPreview() {
PreviewWithTheme {
ContributionContent(
state = State(
listState = ContributionListState(
error = DomainContract.BillingError.DeveloperError("Developer error"),
isLoading = false,
),
),
onEvent = {},
contentPadding = PaddingValues(),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@ package app.k9mail.feature.funding.googleplay.ui.contribution
import androidx.compose.runtime.Composable
import androidx.compose.ui.tooling.preview.Preview
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
import app.k9mail.feature.funding.googleplay.domain.DomainContract
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
import kotlinx.collections.immutable.persistentListOf

@Composable
@Preview(showBackground = true)
internal fun ContributionListPreview() {
PreviewWithTheme {
ContributionList(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = FakeData.recurringContributions,
isRecurringContributionSelected = true,
selectedItem = FakeData.recurringContributions.first(),
state = ContributionListState(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = FakeData.recurringContributions,
selectedContribution = FakeData.recurringContributions.first(),
isRecurringContributionSelected = true,
isLoading = false,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}
Expand All @@ -26,13 +32,17 @@ internal fun ContributionListPreview() {
internal fun ContributionListRecurringPreview() {
PreviewWithTheme {
ContributionList(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = FakeData.recurringContributions,
selectedItem = FakeData.oneTimeContributions.last(),
isRecurringContributionSelected = false,
state = ContributionListState(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = FakeData.recurringContributions,
selectedContribution = FakeData.oneTimeContributions.last(),
isRecurringContributionSelected = false,
isLoading = false,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}
Expand All @@ -42,13 +52,17 @@ internal fun ContributionListRecurringPreview() {
internal fun ContributionListOneTimeOnlyPreview() {
PreviewWithTheme {
ContributionList(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = persistentListOf(),
selectedItem = null,
isRecurringContributionSelected = false,
state = ContributionListState(
oneTimeContributions = FakeData.oneTimeContributions,
recurringContributions = persistentListOf(),
selectedContribution = null,
isRecurringContributionSelected = false,
isLoading = false,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}
Expand All @@ -58,13 +72,17 @@ internal fun ContributionListOneTimeOnlyPreview() {
internal fun ContributionListRecurringOnlyPreview() {
PreviewWithTheme {
ContributionList(
oneTimeContributions = persistentListOf(),
recurringContributions = FakeData.recurringContributions,
selectedItem = null,
isRecurringContributionSelected = true,
state = ContributionListState(
oneTimeContributions = persistentListOf(),
recurringContributions = FakeData.recurringContributions,
selectedContribution = null,
isRecurringContributionSelected = true,
isLoading = false,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}
Expand All @@ -74,13 +92,60 @@ internal fun ContributionListRecurringOnlyPreview() {
internal fun ContributionListEmptyPreview() {
PreviewWithTheme {
ContributionList(
oneTimeContributions = persistentListOf(),
recurringContributions = persistentListOf(),
selectedItem = null,
isRecurringContributionSelected = false,
state = ContributionListState(
oneTimeContributions = persistentListOf(),
recurringContributions = persistentListOf(),
selectedContribution = null,
isRecurringContributionSelected = false,
isLoading = false,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}

@Composable
@Preview(showBackground = true)
internal fun ContributionListLoadingPreview() {
PreviewWithTheme {
ContributionList(
state = ContributionListState(
oneTimeContributions = persistentListOf(),
recurringContributions = persistentListOf(),
selectedContribution = null,
isRecurringContributionSelected = false,
isLoading = true,
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}

@Composable
@Preview(showBackground = true)
internal fun ContributionListErrorPreview() {
PreviewWithTheme {
ContributionList(
state = ContributionListState(
oneTimeContributions = persistentListOf(),
recurringContributions = persistentListOf(),
selectedContribution = null,
isRecurringContributionSelected = false,
isLoading = false,
error = DomainContract.BillingError.UnknownError(
"An error occurred",
),
),
onOneTimeContributionTypeClick = {},
onRecurringContributionTypeClick = {},
onItemClick = {},
onRetryClick = {},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package app.k9mail.feature.funding.googleplay.ui.contribution
import androidx.compose.runtime.Composable
import app.k9mail.core.ui.compose.common.annotation.PreviewDevicesWithBackground
import app.k9mail.core.ui.compose.designsystem.PreviewWithTheme
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ContributionListState
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State

@Composable
Expand All @@ -13,9 +14,11 @@ fun ContributionScreenPreview() {
onBack = {},
viewModel = FakeContributionViewModel(
initialState = State(
recurringContributions = FakeData.recurringContributions,
oneTimeContributions = FakeData.oneTimeContributions,
selectedContribution = FakeData.recurringContributions.first(),
listState = ContributionListState(
recurringContributions = FakeData.recurringContributions,
oneTimeContributions = FakeData.oneTimeContributions,
selectedContribution = FakeData.recurringContributions.first(),
),
),
),
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package app.k9mail.feature.funding.googleplay.ui.contribution

import app.k9mail.core.ui.compose.common.mvi.BaseViewModel
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Effect
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.Event
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.State
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionContract.ViewModel

internal class FakeContributionViewModel(
initialState: State,
) : BaseViewModel<State, Event, Nothing>(initialState = initialState), ViewModel {
) : BaseViewModel<State, Event, Effect>(initialState = initialState), ViewModel {

val events = mutableListOf<Event>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import app.k9mail.feature.funding.googleplay.data.remote.GoogleBillingPurchaseHa
import app.k9mail.feature.funding.googleplay.domain.BillingManager
import app.k9mail.feature.funding.googleplay.domain.ContributionIdProvider
import app.k9mail.feature.funding.googleplay.domain.DomainContract
import app.k9mail.feature.funding.googleplay.domain.usecase.GetAvailableContributions
import app.k9mail.feature.funding.googleplay.ui.contribution.ContributionViewModel
import com.android.billingclient.api.ProductDetails
import org.koin.androidx.viewmodel.dsl.viewModel
Expand Down Expand Up @@ -70,9 +71,16 @@ val featureFundingModule = module {
)
}

single<DomainContract.UseCase.GetAvailableContributions> {
GetAvailableContributions(
billingManager = get(),
)
}

viewModel {
ContributionViewModel(
billingManager = get(),
getAvailableContributions = get(),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ internal class GoogleBillingClient(
}

override suspend fun loadPurchasedRecurringContributions(): Outcome<List<RecurringContribution>, BillingError> {
val purchasesResult = queryPurchase(ProductType.INAPP)
val purchasesResult = queryPurchase(ProductType.SUBS)
return resultMapper.mapToOutcome(purchasesResult.billingResult) {
purchaseHandler.handleRecurringPurchases(clientProvider, purchasesResult.purchasesList)
}.mapFailure { billingError, _ ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.android.billingclient.api.PurchasesUpdatedListener
/**
* Google Billing client provider.
*
* * It is responsible for creating and managing the billing client instance
* It is responsible for creating and managing the billing client instance
*/
class GoogleBillingClientProvider(
private val context: Context,
Expand All @@ -18,12 +18,7 @@ class GoogleBillingClientProvider(
private var clientInstance: BillingClient? = null

override val current: BillingClient
get() = if (clientInstance != null) {
clientInstance!!
} else {
clientInstance = createBillingClient()
clientInstance!!
}
get() = clientInstance ?: createBillingClient().also { clientInstance = it }

private var listener: PurchasesUpdatedListener? = null

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ internal class GoogleBillingPurchaseHandler(

override suspend fun handleRecurringPurchases(
clientProvider: Remote.GoogleBillingClientProvider,
purchases: List<Purchase>
purchases: List<Purchase>,
): List<RecurringContribution> {
return purchases.flatMap { purchase ->
handleRecurringPurchase(clientProvider.current, purchase)
Expand Down Expand Up @@ -131,7 +131,6 @@ internal class GoogleBillingPurchaseHandler(
return extractOneTimeContributions(purchase) + extractRecurringContributions(purchase)
}


private fun extractOneTimeContributions(purchase: Purchase): List<OneTimeContribution> {
if (purchase.purchaseState != Purchase.PurchaseState.PURCHASED) {
return emptyList()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package app.k9mail.feature.funding.googleplay.domain

import android.app.Activity
import app.k9mail.feature.funding.googleplay.domain.entity.AvailableContributions
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
Expand All @@ -9,6 +10,12 @@ import kotlinx.coroutines.flow.StateFlow

interface DomainContract {

interface UseCase {
fun interface GetAvailableContributions {
suspend operator fun invoke(): Outcome<AvailableContributions, BillingError>
}
}

interface ContributionIdProvider {
val oneTimeContributionIds: ImmutableList<String>
val recurringContributionIds: ImmutableList<String>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package app.k9mail.feature.funding.googleplay.domain.entity

data class AvailableContributions(
val oneTimeContributions: List<OneTimeContribution>,
val recurringContributions: List<RecurringContribution>,
val purchasedContribution: Contribution? = null,
)
Loading

0 comments on commit ce1434b

Please sign in to comment.