Skip to content

Commit

Permalink
Implement extend subscription
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandarIlic committed Nov 11, 2024
1 parent b56c421 commit f776862
Show file tree
Hide file tree
Showing 10 changed files with 92 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const val RENDER_TYPE = "renderType"
inline val SavedStateHandle.renderType: String
get() = get<String>(RENDER_TYPE) ?: throw IllegalArgumentException("Missing required renderType argument.")

const val EXTEND_EXISTING_PREMIUM_NAME = "extendExistingPremiumName"
inline val SavedStateHandle.extendExistingPremiumName: String? get() = get(EXTEND_EXISTING_PREMIUM_NAME)

const val INITIAL_QUERY = "initialQuery"
inline val SavedStateHandle.initialQuery: String? get() = get(INITIAL_QUERY)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ fun NavController.navigateToExploreFeed(
private fun NavController.navigateToBookmarks() = navigate(route = "bookmarks")

private fun NavController.navigateToPremiumBuying() = navigate(route = "premium/buying")
private fun NavController.navigateToPremiumExtendSubscription(primalName: String) =
navigate(route = "premium/buying?$EXTEND_EXISTING_PREMIUM_NAME=$primalName")

private fun NavController.navigateToPremiumHome() = navigate(route = "premium/home")
private fun NavController.navigateToPremiumSupportPrimal() = navigate(route = "premium/supportPrimal")
private fun NavController.navigateToPremiumMoreInfo() = navigate(route = "premium/info")
Expand Down Expand Up @@ -435,7 +438,16 @@ fun PrimalAppNavigation() {
),
)

premiumBuying(route = "premium/buying", navController = navController)
premiumBuying(
route = "premium/buying?$EXTEND_EXISTING_PREMIUM_NAME={$EXTEND_EXISTING_PREMIUM_NAME}",
arguments = listOf(
navArgument(EXTEND_EXISTING_PREMIUM_NAME) {
type = NavType.StringType
nullable = true
},
),
navController = navController,
)

premiumHome(route = "premium/home", navController = navController)

Expand Down Expand Up @@ -930,25 +942,29 @@ private fun NavGraphBuilder.advancedSearch(
)
}

private fun NavGraphBuilder.premiumBuying(route: String, navController: NavController) =
composable(
route = route,
enterTransition = { primalSlideInHorizontallyFromEnd },
exitTransition = { primalScaleOut },
popEnterTransition = { primalScaleIn },
popExitTransition = { primalSlideOutHorizontallyToEnd },
) {
val viewModel = hiltViewModel<PremiumBuyingViewModel>()
private fun NavGraphBuilder.premiumBuying(
route: String,
arguments: List<NamedNavArgument>,
navController: NavController,
) = composable(
route = route,
arguments = arguments,
enterTransition = { primalSlideInHorizontallyFromEnd },
exitTransition = { primalScaleOut },
popEnterTransition = { primalScaleIn },
popExitTransition = { primalSlideOutHorizontallyToEnd },
) {
val viewModel = hiltViewModel<PremiumBuyingViewModel>()

ApplyEdgeToEdge()
LockToOrientationPortrait()
ApplyEdgeToEdge()
LockToOrientationPortrait()

PremiumBuyingScreen(
viewModel = viewModel,
onClose = { navController.navigateUp() },
onMoreInfoClick = { navController.navigateToPremiumMoreInfo() },
)
}
PremiumBuyingScreen(
viewModel = viewModel,
onClose = { navController.navigateUp() },
onMoreInfoClick = { navController.navigateToPremiumMoreInfo() },
)
}

private fun NavGraphBuilder.premiumHome(route: String, navController: NavController) =
composable(
Expand Down Expand Up @@ -987,7 +1003,7 @@ private fun NavGraphBuilder.premiumSupportPrimal(route: String, navController: N
viewModel = viewModel,
callbacks = SupportPrimalContract.ScreenCallbacks(
onClose = { navController.navigateUp() },
onBuySubscription = { navController.navigateToPremiumBuying() },
onExtendSubscription = { navController.navigateToPremiumExtendSubscription(primalName = it) },
onBecomeLegend = { navController.navigateToPremiumBecomeLegend() },
),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import net.primal.android.wallet.store.domain.SubscriptionProduct
interface PremiumBuyingContract {
data class UiState(
val loading: Boolean = true,
val isExtendingPremium: Boolean = false,
val subscriptions: List<SubscriptionProduct> = emptyList(),
val stage: PremiumStage = PremiumStage.Home,
val primalName: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,15 @@ private fun PremiumBuyingScreen(
state = state,
eventPublisher = eventPublisher,
onBack = {
eventPublisher(
PremiumBuyingContract.UiEvent.MoveToPremiumStage(
PremiumBuyingContract.PremiumStage.FindPrimalName,
),
)
if (state.isExtendingPremium) {
onClose()
} else {
eventPublisher(
PremiumBuyingContract.UiEvent.MoveToPremiumStage(
PremiumBuyingContract.PremiumStage.FindPrimalName,
),
)
}
},
onLearnMoreClick = onMoreInfoClick,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package net.primal.android.premium.buying

import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -13,7 +14,9 @@ import kotlinx.coroutines.flow.getAndUpdate
import kotlinx.coroutines.launch
import net.primal.android.core.compose.profile.model.asProfileDetailsUi
import net.primal.android.core.utils.isGoogleBuild
import net.primal.android.navigation.extendExistingPremiumName
import net.primal.android.networking.sockets.errors.WssException
import net.primal.android.premium.buying.PremiumBuyingContract.PremiumStage
import net.primal.android.premium.buying.PremiumBuyingContract.UiEvent
import net.primal.android.premium.buying.PremiumBuyingContract.UiState
import net.primal.android.premium.domain.MembershipError
Expand All @@ -27,6 +30,7 @@ import timber.log.Timber

@HiltViewModel
class PremiumBuyingViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
private val primalBillingClient: PrimalBillingClient,
private val premiumRepository: PremiumRepository,
private val profileRepository: ProfileRepository,
Expand All @@ -35,7 +39,13 @@ class PremiumBuyingViewModel @Inject constructor(

private var purchase: SubscriptionPurchase? = null

private val _state = MutableStateFlow(UiState())
private val _state = MutableStateFlow(
UiState(
isExtendingPremium = savedStateHandle.extendExistingPremiumName != null,
primalName = savedStateHandle.extendExistingPremiumName,
stage = if (savedStateHandle.extendExistingPremiumName != null) PremiumStage.Purchase else PremiumStage.Home,
),
)
val state = _state.asStateFlow()
private fun setState(reducer: UiState.() -> UiState) = _state.getAndUpdate { it.reducer() }

Expand Down Expand Up @@ -108,7 +118,7 @@ class PremiumBuyingViewModel @Inject constructor(
primalName = primalName,
purchase = purchase,
)
setState { copy(stage = PremiumBuyingContract.PremiumStage.Success) }
setState { copy(stage = PremiumStage.Success) }
} catch (error: WssException) {
Timber.e(error)
this@PremiumBuyingViewModel.purchase = purchase
Expand Down Expand Up @@ -154,7 +164,7 @@ class PremiumBuyingViewModel @Inject constructor(
primalName = primalName,
purchase = existingPurchase,
)
setState { copy(stage = PremiumBuyingContract.PremiumStage.Success) }
setState { copy(stage = PremiumStage.Success) }
premiumRepository.fetchMembershipStatus(userId = userId)
} catch (error: WssException) {
Timber.e(error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,11 @@ fun PremiumPurchaseStage(
Scaffold(
topBar = {
PrimalTopAppBar(
title = stringResource(id = R.string.premium_purchase_title),
title = if (state.isExtendingPremium) {
stringResource(id = R.string.premium_extend_subscription_title)
} else {
stringResource(id = R.string.premium_purchase_title)
},
navigationIcon = PrimalIcons.ArrowBack,
onNavigationIconClick = onBack,
showDivider = false,
Expand Down Expand Up @@ -120,17 +124,29 @@ fun PremiumPurchaseStage(
internetIdentifierBadgeSize = 24.dp,
fontSize = 20.sp,
)
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = stringResource(id = R.string.premium_purchase_primal_name_available),
style = AppTheme.typography.bodyLarge,
color = AppTheme.extraColorScheme.successBright,
)
if (!state.isExtendingPremium) {
Text(
modifier = Modifier.padding(horizontal = 12.dp),
text = stringResource(id = R.string.premium_purchase_primal_name_available),
style = AppTheme.typography.bodyLarge,
color = AppTheme.extraColorScheme.successBright,
)
}
PremiumPrimalNameTable(
primalName = state.primalName,
)
}

if (state.isExtendingPremium) {
Text(
modifier = Modifier.padding(horizontal = 32.dp),
text = stringResource(id = R.string.premium_extend_subscription_notice),
style = AppTheme.typography.bodyMedium,
color = AppTheme.extraColorScheme.onSurfaceVariantAlt2,
textAlign = TextAlign.Center,
)
}

MoreInfoPromoCodeRow(
modifier = Modifier.padding(vertical = 8.dp),
onLearnMoreClick = onLearnMoreClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ package net.primal.android.premium.support
interface SupportPrimalContract {

data class UiState(
val primalName: String? = null,
val hasMembership: Boolean = false,
val isPrimalLegend: Boolean = false,
)

data class ScreenCallbacks(
val onClose: () -> Unit,
val onBuySubscription: () -> Unit,
val onExtendSubscription: (primalName: String) -> Unit,
val onBecomeLegend: () -> Unit,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,14 @@ private fun SupportPrimalScreen(

Spacer(modifier = Modifier.height(20.dp))

if (!state.hasMembership || true) {
if (!state.hasMembership) {
SupportCard(
modifier = Modifier.fillMaxSize(),
painter = painterResource(R.drawable.support_primal_buy_subscription),
title = stringResource(R.string.premium_support_primal_buy_subscription_title),
description = stringResource(R.string.premium_support_primal_buy_subscription_description),
buttonText = stringResource(R.string.premium_support_primal_buy_subscription_button_text),
onClick = callbacks.onBuySubscription,
onClick = { if (state.primalName != null) callbacks.onExtendSubscription(state.primalName) },
)

Spacer(modifier = Modifier.height(20.dp))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ class SupportPrimalViewModel @Inject constructor(
activeAccountStore.activeUserAccount.collect {
setState {
copy(
primalName = it.premiumMembership?.premiumName,
isPrimalLegend = it.premiumMembership?.cohort2.isPrimalLegend(),
hasMembership = it.premiumMembership != null && !it.premiumMembership.cohort2.isPremiumFree(),
)
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@
<string name="premium_purchase_tos_notice">By proceeding you acknowledge that\nyou agree to our </string>
<string name="premium_purchase_tos">Terms of Service</string>

<string name="premium_extend_subscription_title">Extend Subscription</string>
<string name="premium_extend_subscription_notice">Your subscription will be extended by the number of months you buy.</string>

<string name="premium_success_purchase_title">Success</string>
<string name="premium_success_purchase_headline">Success, payment received!</string>
<string name="premium_success_purchase_supporting_text">Your subscription is now active!</string>
Expand Down

0 comments on commit f776862

Please sign in to comment.