Frontend Spec: RevenueCat Pro Paywall Subscription Modal Composable (PaywallModal)
Estado de fase (MASTER-00): MVP — alcance del MVP Shipaton sujeto a resultados de Gate 0 y PoC. Gobernanza: MASTER-00.
Frontend Spec: RevenueCat Pro Paywall Subscription Modal Composable (PaywallModal)
Sección titulada «Frontend Spec: RevenueCat Pro Paywall Subscription Modal Composable (PaywallModal)»1. Overview & Purpose
Sección titulada «1. Overview & Purpose»This specification details the subscription paywall dialog (PaywallModal) in :docugraph-app. It renders Pro tier benefits (unlimited projects, unrestricted context depth, cloud sync, automated CI/CD audits), displays monthly vs yearly pricing tiers fetched via RevenueCat Mobile SDK / REST API, manages purchase flows, updates local session tokens upon success, and syncs offline grace limits.
2. Component Signature & Props
Sección titulada «2. Component Signature & Props»package io.docugraph.app.ui.paywall
import androidx.compose.runtime.Composableimport androidx.compose.ui.Modifier
@Composablefun PaywallModal( isOpen: Boolean, onDismiss: () -> Unit, onPurchaseSuccess: () -> Unit, viewModel: PaywallViewModel, modifier: Modifier = Modifier)3. UI State Model & Data Classes
Sección titulada «3. UI State Model & Data Classes»package io.docugraph.app.ui.paywall
enum class SubscriptionPlan { MONTHLY_PRO, // $19 / month YEARLY_PRO // $190 / year (2 months free)}
data class PaywallUiState( val selectedPlan: SubscriptionPlan = SubscriptionPlan.YEARLY_PRO, val isPurchasing: Boolean = false, val monthlyPriceString: String = "$19.00 / mo", val yearlyPriceString: String = "$190.00 / yr", val errorMessage: String? = null, val purchaseSuccessBanner: Boolean = false)4. UI Layout Hierarchy & Composables
Sección titulada «4. UI Layout Hierarchy & Composables»Dialog (if isOpen, onDismissRequest = onDismiss) └── Card (Modifier.width(520.dp), shape = RoundedCornerShape(16.dp)) └── Column (Padding 24.dp) ├── HeaderRow │ ├── Text ("Upgrade to DocuGraph Pro 🚀", style = HeadlineSmall) │ └── IconButton (Close -> onDismiss()) ├── Text ("Unlock maximum productivity for AI coding agents", style = BodyMedium) ├── Spacer (Height 20.dp) ├── FeatureMatrixColumn │ ├── FeatureItem (Icon: Check, Text: "Unlimited Active Projects (Free tier capped at 3)") │ ├── FeatureItem (Icon: Check, Text: "Unrestricted MCP Traversal Depth (Free tier capped at depth=2)") │ ├── FeatureItem (Icon: Check, Text: "Automated CI/CD Traceability Audits") │ └── FeatureItem (Icon: Check, Text: "7-Day Offline Grace Mode") ├── Spacer (Height 24.dp) ├── PlanSelectionRow │ ├── PlanCard (Monthly, Selected = selectedPlan == MONTHLY_PRO, OnClick = selectMonthly) │ └── PlanCard (Yearly - Best Value Badge, Selected = selectedPlan == YEARLY_PRO, OnClick = selectYearly) ├── Spacer (Height 24.dp) ├── AnimatedVisibility (errorMessage != null) │ └── ErrorText (errorMessage) ├── Button ("Subscribe Now") │ ├── Enabled = !isPurchasing │ └── Content: if (isPurchasing) CircularProgressIndicator else Text("Start Pro Subscription") ├── Spacer (Height 12.dp) └── TextButton ("Restore Purchases", onClick = restorePurchases)5. RevenueCat Mobile SDK Purchase Flow & Token Sync
Sección titulada «5. RevenueCat Mobile SDK Purchase Flow & Token Sync»fun executePurchase(plan: SubscriptionPlan) { viewModelScope.launch { _uiState.update { it.copy(isPurchasing = true) } try { val packageToPurchase = getRevenueCatPackage(plan) val purchaseResult = revenueCatSdk.purchasePackage(packageToPurchase)
if (purchaseResult.customerInfo.entitlements["pro_tier"]?.isActive == true) { // Sync updated entitlement with backend BE-06 checkEntitlement authRepository.refreshUserTokens() _uiState.update { it.copy(isPurchasing = false, purchaseSuccessBanner = true) } onPurchaseSuccess() } } catch (e: UserCancelledException) { _uiState.update { it.copy(isPurchasing = false) } } catch (e: Exception) { _uiState.update { it.copy(isPurchasing = false, errorMessage = e.message) } } }}6. Verification & Test Plan
Sección titulada «6. Verification & Test Plan»- Screenshot Test: Render
PaywallModalpreview with Yearly plan selected and feature list. - UiTest: Tap “Subscribe Now”, mock RevenueCat SDK success response, verify
onPurchaseSuccessinvoked and token refreshed.