@umituz/react-native-subscription 2.14.99 → 2.14.101
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +211 -394
- package/package.json +3 -3
- package/src/application/README.md +46 -225
- package/src/application/ports/README.md +42 -97
- package/src/domain/README.md +36 -384
- package/src/domain/constants/README.md +0 -56
- package/src/domain/entities/README.md +43 -169
- package/src/domain/entities/SubscriptionStatus.ts +1 -1
- package/src/domain/errors/README.md +33 -287
- package/src/domain/value-objects/README.md +43 -179
- package/src/domains/README.md +50 -238
- package/src/domains/README.md.bak +274 -0
- package/src/domains/config/README.md +93 -383
- package/src/domains/config/domain/README.md +23 -376
- package/src/domains/config/domain/entities/README.md +34 -343
- package/src/domains/paywall/README.md +99 -369
- package/src/domains/paywall/components/README.md +34 -178
- package/src/domains/paywall/entities/README.md +34 -193
- package/src/domains/paywall/hooks/README.md +34 -122
- package/src/domains/wallet/README.md +34 -275
- package/src/domains/wallet/README.md.bak +209 -0
- package/src/domains/wallet/domain/README.md +34 -101
- package/src/domains/wallet/domain/entities/README.md +34 -115
- package/src/domains/wallet/domain/errors/README.md +34 -151
- package/src/domains/wallet/infrastructure/README.md +34 -89
- package/src/domains/wallet/presentation/components/README.md +34 -224
- package/src/domains/wallet/presentation/components/TransactionItem.tsx +1 -1
- package/src/domains/wallet/presentation/hooks/README.md +34 -248
- package/src/infrastructure/README.md +37 -496
- package/src/infrastructure/mappers/README.md +0 -13
- package/src/infrastructure/repositories/README.md +74 -360
- package/src/infrastructure/services/ActivationHandler.ts +1 -1
- package/src/infrastructure/services/README.md +95 -370
- package/src/infrastructure/services/SubscriptionService.ts +1 -1
- package/src/presentation/README.md +123 -408
- package/src/presentation/README.md.bak +172 -0
- package/src/presentation/components/README.md +151 -179
- package/src/presentation/components/README.md.bak +217 -0
- package/src/presentation/components/details/CreditRow.md +65 -310
- package/src/presentation/components/details/DetailRow.md +63 -255
- package/src/presentation/components/details/PremiumDetailsCard.md +65 -238
- package/src/presentation/components/details/PremiumStatusBadge.md +64 -239
- package/src/presentation/components/details/README.md +97 -447
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +63 -287
- package/src/presentation/components/feedback/README.md +97 -445
- package/src/presentation/components/paywall/PaywallModal.md +66 -416
- package/src/presentation/components/paywall/README.md +50 -186
- package/src/presentation/components/sections/README.md +97 -466
- package/src/presentation/components/sections/SubscriptionSection.md +92 -244
- package/src/presentation/hooks/README.md +154 -741
- package/src/presentation/hooks/useAuthAwarePurchase.md +58 -325
- package/src/presentation/hooks/useAuthGate.md +61 -375
- package/src/presentation/hooks/useAuthSubscriptionSync.md +66 -370
- package/src/presentation/hooks/useCreditChecker.md +73 -378
- package/src/presentation/hooks/useCredits.md +74 -313
- package/src/presentation/hooks/useCredits.md.bak +231 -0
- package/src/presentation/hooks/useCreditsGate.md +66 -318
- package/src/presentation/hooks/useDeductCredit.md +0 -76
- package/src/presentation/hooks/useDeductCredit.ts +1 -1
- package/src/presentation/hooks/useDevTestCallbacks.md +63 -394
- package/src/presentation/hooks/useFeatureGate.md +105 -150
- package/src/presentation/hooks/useFeatureGate.md.bak +284 -0
- package/src/presentation/hooks/useInitializeCredits.md +64 -430
- package/src/presentation/hooks/usePaywall.md +61 -306
- package/src/presentation/hooks/usePaywallOperations.md +64 -458
- package/src/presentation/hooks/usePaywallVisibility.md +67 -316
- package/src/presentation/hooks/usePremium.md +84 -226
- package/src/presentation/hooks/usePremiumGate.md +60 -395
- package/src/presentation/hooks/usePremiumWithCredits.md +64 -401
- package/src/presentation/hooks/useSubscription.md +66 -422
- package/src/presentation/hooks/useSubscriptionDetails.md +65 -410
- package/src/presentation/hooks/useSubscriptionGate.md +80 -164
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +66 -346
- package/src/presentation/hooks/useSubscriptionStatus.md +66 -396
- package/src/presentation/hooks/useUserTier.md +63 -328
- package/src/presentation/hooks/useUserTierWithRepository.md +64 -424
- package/src/presentation/screens/README.md +48 -190
- package/src/presentation/types/README.md +0 -16
- package/src/presentation/utils/README.md +0 -21
- package/src/presentation/utils/subscriptionDateUtils.ts +1 -1
- package/src/revenuecat/README.md +99 -518
- package/src/revenuecat/application/README.md +35 -150
- package/src/revenuecat/application/ports/README.md +34 -162
- package/src/revenuecat/domain/README.md +42 -141
- package/src/revenuecat/domain/constants/README.md +34 -176
- package/src/revenuecat/domain/entities/README.md +34 -374
- package/src/revenuecat/domain/errors/README.md +47 -191
- package/src/revenuecat/domain/types/README.md +34 -366
- package/src/revenuecat/domain/value-objects/README.md +34 -434
- package/src/revenuecat/infrastructure/README.md +34 -43
- package/src/revenuecat/infrastructure/config/README.md +32 -23
- package/src/revenuecat/infrastructure/handlers/README.md +34 -211
- package/src/revenuecat/infrastructure/managers/README.md +34 -42
- package/src/revenuecat/infrastructure/services/README.md +35 -318
- package/src/revenuecat/infrastructure/utils/README.md +34 -375
- package/src/revenuecat/presentation/README.md +34 -176
- package/src/revenuecat/presentation/hooks/README.md +29 -35
- package/src/utils/README.md +38 -525
|
@@ -2,437 +2,92 @@
|
|
|
2
2
|
|
|
3
3
|
Hook for accessing detailed subscription information including package details.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Location
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
import { useSubscriptionDetails } from '@umituz/react-native-subscription';
|
|
9
|
-
```
|
|
7
|
+
**Import Path**: `@umituz/react-native-subscription`
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
**File**: `src/presentation/hooks/useSubscriptionDetails.ts`
|
|
12
10
|
|
|
13
|
-
|
|
14
|
-
function useSubscriptionDetails(): {
|
|
15
|
-
subscription: SubscriptionStatus | null;
|
|
16
|
-
package: Package | null;
|
|
17
|
-
period: PackagePeriod | null;
|
|
18
|
-
price: number | null;
|
|
19
|
-
pricePerMonth: number | null;
|
|
20
|
-
features: string[] | null;
|
|
21
|
-
isLoading: boolean;
|
|
22
|
-
error: Error | null;
|
|
23
|
-
refetch: () => Promise<void>;
|
|
24
|
-
}
|
|
25
|
-
```
|
|
11
|
+
**Type**: Hook
|
|
26
12
|
|
|
27
|
-
##
|
|
13
|
+
## Strategy
|
|
28
14
|
|
|
29
|
-
|
|
30
|
-
|----------|------|-------------|
|
|
31
|
-
| `subscription` | `SubscriptionStatus \| null` | Subscription status object |
|
|
32
|
-
| `package` | `Package \| null` | RevenueCat package object |
|
|
33
|
-
| `period` | `'monthly' \| 'annual' \| 'lifetime' \| null` | Subscription period |
|
|
34
|
-
| `price` | `number \| null` | Current price |
|
|
35
|
-
| `pricePerMonth` | `number \| null` | Monthly equivalent price |
|
|
36
|
-
| `features` | `string[] \| null` | List of features |
|
|
37
|
-
| `isLoading` | `boolean` | Loading state |
|
|
38
|
-
| `error` | `Error \| null` | Error if any |
|
|
15
|
+
### Detailed Subscription Information
|
|
39
16
|
|
|
40
|
-
|
|
17
|
+
1. **Subscription Status**: Fetch current subscription status object
|
|
18
|
+
2. **Package Details**: Retrieve RevenueCat package information
|
|
19
|
+
3. **Period Detection**: Determine subscription period (monthly/annual/lifetime)
|
|
20
|
+
4. **Price Calculation**: Calculate current price and monthly equivalent
|
|
21
|
+
5. **Feature List**: Extract feature list from package configuration
|
|
22
|
+
6. **Real-time Updates**: Refresh when subscription changes
|
|
41
23
|
|
|
42
|
-
|
|
43
|
-
function SubscriptionDetails() {
|
|
44
|
-
const {
|
|
45
|
-
subscription,
|
|
46
|
-
package,
|
|
47
|
-
period,
|
|
48
|
-
price,
|
|
49
|
-
features,
|
|
50
|
-
isLoading,
|
|
51
|
-
} = useSubscriptionDetails();
|
|
24
|
+
### Integration Points
|
|
52
25
|
|
|
53
|
-
|
|
26
|
+
- **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
|
|
27
|
+
- **Package Configuration**: RevenueCat package definitions
|
|
28
|
+
- **useSubscriptionStatus**: For detailed status information
|
|
29
|
+
- **TanStack Query**: For caching and background updates
|
|
54
30
|
|
|
55
|
-
|
|
56
|
-
<View>
|
|
57
|
-
<Text>Plan: {package?.product.title}</Text>
|
|
58
|
-
<Text>Price: {price} / {period}</Text>
|
|
59
|
-
<Text>Features:</Text>
|
|
60
|
-
{features?.map((feature, index) => (
|
|
61
|
-
<Text key={index}>• {feature}</Text>
|
|
62
|
-
))}
|
|
63
|
-
</View>
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
```
|
|
31
|
+
## Restrictions
|
|
67
32
|
|
|
68
|
-
|
|
33
|
+
### REQUIRED
|
|
69
34
|
|
|
70
|
-
|
|
35
|
+
- **Loading State**: MUST handle loading state
|
|
36
|
+
- **Null Handling**: MUST handle null subscription and package
|
|
37
|
+
- **Error Handling**: MUST handle error state
|
|
38
|
+
- **Price Formatting**: MUST format prices appropriately
|
|
71
39
|
|
|
72
|
-
|
|
73
|
-
function DetailedSubscriptionCard() {
|
|
74
|
-
const {
|
|
75
|
-
subscription,
|
|
76
|
-
package,
|
|
77
|
-
period,
|
|
78
|
-
price,
|
|
79
|
-
pricePerMonth,
|
|
80
|
-
features,
|
|
81
|
-
} = useSubscriptionDetails();
|
|
40
|
+
### PROHIBITED
|
|
82
41
|
|
|
83
|
-
|
|
42
|
+
- **NEVER** assume subscription exists (check for null)
|
|
43
|
+
- **NEVER** assume package exists (check for null)
|
|
44
|
+
- **DO NOT** use prices without formatting
|
|
45
|
+
- **DO NOT** hardcode feature lists
|
|
84
46
|
|
|
85
|
-
|
|
86
|
-
<Card>
|
|
87
|
-
<Card.Title>
|
|
88
|
-
{package.product.title}
|
|
89
|
-
</Card.Title>
|
|
47
|
+
### CRITICAL SAFETY
|
|
90
48
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
/>
|
|
49
|
+
- **ALWAYS** check for null subscription and package
|
|
50
|
+
- **MUST** handle loading state before accessing details
|
|
51
|
+
- **ALWAYS** format prices with currency codes
|
|
52
|
+
- **NEVER** trust client-side details for security
|
|
96
53
|
|
|
97
|
-
|
|
98
|
-
label="Price"
|
|
99
|
-
value={`${price} ${package?.product.currencyCode}`}
|
|
100
|
-
/>
|
|
54
|
+
## AI Agent Guidelines
|
|
101
55
|
|
|
102
|
-
|
|
103
|
-
<DetailRow
|
|
104
|
-
label="Per Month"
|
|
105
|
-
value={`${pricePerMonth.toFixed(2)} ${package?.product.currencyCode}`}
|
|
106
|
-
/>
|
|
107
|
-
)}
|
|
56
|
+
### When Implementing Subscription Details
|
|
108
57
|
|
|
109
|
-
|
|
58
|
+
1. **Always** check for null subscription and package
|
|
59
|
+
2. **Always** handle loading state
|
|
60
|
+
3. **Always** format prices properly
|
|
61
|
+
4. **Always** handle all period types (monthly, annual, lifetime)
|
|
62
|
+
5. **Never** use for security decisions without server validation
|
|
110
63
|
|
|
111
|
-
|
|
112
|
-
{features?.map((feature, index) => (
|
|
113
|
-
<FeatureItem key={index} feature={feature} />
|
|
114
|
-
))}
|
|
115
|
-
</Card.Body>
|
|
116
|
-
</Card>
|
|
117
|
-
);
|
|
118
|
-
}
|
|
119
|
-
```
|
|
64
|
+
### Integration Checklist
|
|
120
65
|
|
|
121
|
-
|
|
66
|
+
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
67
|
+
- [ ] Handle loading state
|
|
68
|
+
- [ ] Check subscription for null
|
|
69
|
+
- [ ] Check package for null
|
|
70
|
+
- [ ] Format prices with currency codes
|
|
71
|
+
- [ ] Handle all period types
|
|
72
|
+
- [ ] Display features properly
|
|
73
|
+
- [ ] Test with monthly subscription
|
|
74
|
+
- [ ] Test with annual subscription
|
|
75
|
+
- [ ] Test with lifetime subscription
|
|
76
|
+
- [ ] Test with no subscription
|
|
122
77
|
|
|
123
|
-
|
|
124
|
-
function PriceComparison() {
|
|
125
|
-
const { price, period, pricePerMonth } = useSubscriptionDetails();
|
|
78
|
+
### Common Patterns
|
|
126
79
|
|
|
127
|
-
|
|
80
|
+
1. **Detailed Card**: Display comprehensive subscription information
|
|
81
|
+
2. **Price Comparison**: Show monthly vs annual pricing
|
|
82
|
+
3. **Upgrade Suggestion**: Suggest upgrades based on current plan
|
|
83
|
+
4. **Feature List**: Display included features
|
|
84
|
+
5. **Billing History**: Show subscription history
|
|
85
|
+
6. **Cancellation Flow**: Handle subscription cancellation
|
|
128
86
|
|
|
129
|
-
|
|
130
|
-
monthly: price,
|
|
131
|
-
annual: pricePerMonth ? pricePerMonth * 12 : price,
|
|
132
|
-
};
|
|
87
|
+
## Related Documentation
|
|
133
88
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{period === 'annual' && (
|
|
140
|
-
<SavingsBadge
|
|
141
|
-
original={monthlyPrices.monthly * 12}
|
|
142
|
-
current={price}
|
|
143
|
-
/>
|
|
144
|
-
)}
|
|
145
|
-
</View>
|
|
146
|
-
);
|
|
147
|
-
}
|
|
148
|
-
```
|
|
149
|
-
|
|
150
|
-
### With Upgrade Suggestion
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
function UpgradeSuggestion() {
|
|
154
|
-
const {
|
|
155
|
-
subscription,
|
|
156
|
-
package: currentPackage,
|
|
157
|
-
price,
|
|
158
|
-
} = useSubscriptionDetails();
|
|
159
|
-
|
|
160
|
-
const { packages: allPackages } = useSubscriptionPackages();
|
|
161
|
-
|
|
162
|
-
// Find upgrade options
|
|
163
|
-
const upgradeOptions = allPackages.filter(
|
|
164
|
-
(pkg) =>
|
|
165
|
-
pkg.product.price > (currentPackage?.product.price || 0)
|
|
166
|
-
);
|
|
167
|
-
|
|
168
|
-
if (!subscription?.isPremium) {
|
|
169
|
-
return (
|
|
170
|
-
<View>
|
|
171
|
-
<Text>Upgrade to Premium for full access</Text>
|
|
172
|
-
<Button
|
|
173
|
-
onPress={() => navigation.navigate('Paywall')}
|
|
174
|
-
title="View Plans"
|
|
175
|
-
/>
|
|
176
|
-
</View>
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return (
|
|
181
|
-
<View>
|
|
182
|
-
<Text>Current Plan: {currentPackage?.product.title}</Text>
|
|
183
|
-
<Button
|
|
184
|
-
onPress={() => navigation.navigate('ManageSubscription')}
|
|
185
|
-
title="Manage Subscription"
|
|
186
|
-
/>
|
|
187
|
-
</View>
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### With Feature List
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
function FeatureList() {
|
|
196
|
-
const { features } = useSubscriptionDetails();
|
|
197
|
-
|
|
198
|
-
if (!features) return null;
|
|
199
|
-
|
|
200
|
-
const featureIcons = {
|
|
201
|
-
'unlimited_access': '∞',
|
|
202
|
-
'ai_tools': '🤖',
|
|
203
|
-
'ad_free': '🛡️',
|
|
204
|
-
'priority_support': '💬',
|
|
205
|
-
'advanced_filters': '🔍',
|
|
206
|
-
};
|
|
207
|
-
|
|
208
|
-
return (
|
|
209
|
-
<View>
|
|
210
|
-
<Text style={styles.title}>Your Premium Features:</Text>
|
|
211
|
-
|
|
212
|
-
{features.map((feature) => (
|
|
213
|
-
<FeatureItem
|
|
214
|
-
key={feature}
|
|
215
|
-
icon={featureIcons[feature] || '✓'}
|
|
216
|
-
text={formatFeatureName(feature)}
|
|
217
|
-
/>
|
|
218
|
-
))}
|
|
219
|
-
</View>
|
|
220
|
-
);
|
|
221
|
-
}
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
## Examples
|
|
225
|
-
|
|
226
|
-
### Subscription Info Screen
|
|
227
|
-
|
|
228
|
-
```typescript
|
|
229
|
-
function SubscriptionInfoScreen() {
|
|
230
|
-
const {
|
|
231
|
-
subscription,
|
|
232
|
-
package,
|
|
233
|
-
period,
|
|
234
|
-
price,
|
|
235
|
-
features,
|
|
236
|
-
isLoading,
|
|
237
|
-
refetch,
|
|
238
|
-
} = useSubscriptionDetails();
|
|
239
|
-
|
|
240
|
-
useFocusEffect(
|
|
241
|
-
useCallback(() => {
|
|
242
|
-
refetch();
|
|
243
|
-
}, [refetch])
|
|
244
|
-
);
|
|
245
|
-
|
|
246
|
-
if (isLoading) {
|
|
247
|
-
return <LoadingScreen />;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
if (!subscription || !package) {
|
|
251
|
-
return (
|
|
252
|
-
<View>
|
|
253
|
-
<Text>No subscription found</Text>
|
|
254
|
-
<Button
|
|
255
|
-
onPress={() => navigation.navigate('Paywall')}
|
|
256
|
-
title="Subscribe"
|
|
257
|
-
/>
|
|
258
|
-
</View>
|
|
259
|
-
);
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
return (
|
|
263
|
-
<ScrollView>
|
|
264
|
-
{/* Status Banner */}
|
|
265
|
-
<StatusBanner
|
|
266
|
-
isActive={subscription.isActive}
|
|
267
|
-
type={subscription.type}
|
|
268
|
-
/>
|
|
269
|
-
|
|
270
|
-
{/* Package Details */}
|
|
271
|
-
<Card style={styles.section}>
|
|
272
|
-
<Card.Title>Current Plan</Card.Title>
|
|
273
|
-
<Card.Body>
|
|
274
|
-
<Text style={styles.planName}>{package.product.title}</Text>
|
|
275
|
-
<Text style={styles.price}>
|
|
276
|
-
{price} {package.product.currencyCode}
|
|
277
|
-
</Text>
|
|
278
|
-
|
|
279
|
-
{period !== 'lifetime' && (
|
|
280
|
-
<Text style={styles.period}>
|
|
281
|
-
per {period.slice(0, -2)} // "month" -> "month"
|
|
282
|
-
</Text>
|
|
283
|
-
)}
|
|
284
|
-
|
|
285
|
-
{subscription.expirationDate && (
|
|
286
|
-
<Text style={styles.expires}>
|
|
287
|
-
Renews on {new Date(subscription.expirationDate).toLocaleDateString()}
|
|
288
|
-
</Text>
|
|
289
|
-
)}
|
|
290
|
-
</Card.Body>
|
|
291
|
-
</Card>
|
|
292
|
-
|
|
293
|
-
{/* Features */}
|
|
294
|
-
{features && features.length > 0 && (
|
|
295
|
-
<Card style={styles.section}>
|
|
296
|
-
<Card.Title>Features</Card.Title>
|
|
297
|
-
<Card.Body>
|
|
298
|
-
{features.map((feature, index) => (
|
|
299
|
-
<FeatureItem
|
|
300
|
-
key={index}
|
|
301
|
-
icon="✓"
|
|
302
|
-
text={formatFeatureName(feature)}
|
|
303
|
-
/>
|
|
304
|
-
))}
|
|
305
|
-
</Card.Body>
|
|
306
|
-
</Card>
|
|
307
|
-
)}
|
|
308
|
-
|
|
309
|
-
{/* Actions */}
|
|
310
|
-
<Card style={styles.section}>
|
|
311
|
-
<Card.Body>
|
|
312
|
-
<Button
|
|
313
|
-
onPress={() => navigation.navigate('ManageSubscription')}
|
|
314
|
-
title="Manage Subscription"
|
|
315
|
-
/>
|
|
316
|
-
|
|
317
|
-
<Button
|
|
318
|
-
onPress={refetch}
|
|
319
|
-
title="Refresh"
|
|
320
|
-
variant="outline"
|
|
321
|
-
/>
|
|
322
|
-
</Card.Body>
|
|
323
|
-
</Card>
|
|
324
|
-
</ScrollView>
|
|
325
|
-
);
|
|
326
|
-
}
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
### Billing History
|
|
330
|
-
|
|
331
|
-
```typescript
|
|
332
|
-
function BillingHistory() {
|
|
333
|
-
const { subscription, package, price } = useSubscriptionDetails();
|
|
334
|
-
|
|
335
|
-
if (!subscription || !package) return null;
|
|
336
|
-
|
|
337
|
-
const transactions = [
|
|
338
|
-
{
|
|
339
|
-
date: subscription.expirationDate,
|
|
340
|
-
description: `Renewal - ${package.product.title}`,
|
|
341
|
-
amount: price,
|
|
342
|
-
status: 'completed',
|
|
343
|
-
},
|
|
344
|
-
];
|
|
345
|
-
|
|
346
|
-
return (
|
|
347
|
-
<View>
|
|
348
|
-
<Text style={styles.title}>Billing History</Text>
|
|
349
|
-
|
|
350
|
-
{transactions.map((tx, index) => (
|
|
351
|
-
<TransactionItem
|
|
352
|
-
key={index}
|
|
353
|
-
date={tx.date}
|
|
354
|
-
description={tx.description}
|
|
355
|
-
amount={tx.amount}
|
|
356
|
-
status={tx.status}
|
|
357
|
-
/>
|
|
358
|
-
))}
|
|
359
|
-
</View>
|
|
360
|
-
);
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
### Cancellation Flow
|
|
365
|
-
|
|
366
|
-
```typescript
|
|
367
|
-
function CancellationFlow() {
|
|
368
|
-
const { subscription, package, willRenew } = useSubscriptionDetails();
|
|
369
|
-
|
|
370
|
-
const handleCancel = async () => {
|
|
371
|
-
if (!willRenew) {
|
|
372
|
-
Alert.alert('Info', 'Your subscription will not renew');
|
|
373
|
-
return;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
Alert.alert(
|
|
377
|
-
'Cancel Subscription',
|
|
378
|
-
'Your subscription will expire at the end of the current period',
|
|
379
|
-
[
|
|
380
|
-
{ text: 'Keep', style: 'cancel' },
|
|
381
|
-
{
|
|
382
|
-
text: 'Cancel',
|
|
383
|
-
style: 'destructive',
|
|
384
|
-
onPress: async () => {
|
|
385
|
-
// Cancel with RevenueCat
|
|
386
|
-
try {
|
|
387
|
-
// Link to platform-specific subscription management
|
|
388
|
-
if (Platform.OS === 'ios') {
|
|
389
|
-
Linking.openURL('https://apps.apple.com/account/subscriptions');
|
|
390
|
-
} else {
|
|
391
|
-
Linking.openURL('https://play.google.com/store/account/subscriptions');
|
|
392
|
-
}
|
|
393
|
-
} catch (error) {
|
|
394
|
-
Alert.alert('Error', 'Could not open subscription settings');
|
|
395
|
-
}
|
|
396
|
-
},
|
|
397
|
-
},
|
|
398
|
-
]
|
|
399
|
-
);
|
|
400
|
-
};
|
|
401
|
-
|
|
402
|
-
return (
|
|
403
|
-
<View>
|
|
404
|
-
<Text>Plan: {package?.product.title}</Text>
|
|
405
|
-
<Text>Auto-renew: {willRenew ? 'Yes' : 'No'}</Text>
|
|
406
|
-
|
|
407
|
-
<Button
|
|
408
|
-
onPress={handleCancel}
|
|
409
|
-
title="Cancel Subscription"
|
|
410
|
-
color="#F44336"
|
|
411
|
-
/>
|
|
412
|
-
</View>
|
|
413
|
-
);
|
|
414
|
-
}
|
|
415
|
-
```
|
|
416
|
-
|
|
417
|
-
## Best Practices
|
|
418
|
-
|
|
419
|
-
1. **Handle null values** - Check if subscription and package exist
|
|
420
|
-
2. **Format prices** - Use currency formatters
|
|
421
|
-
3. **Display all info** - Show status, price, features
|
|
422
|
-
4. **Provide actions** - Add manage, cancel, upgrade buttons
|
|
423
|
-
5. **Refresh on focus** - Update when screen gains focus
|
|
424
|
-
6. **Handle errors** - Show user-friendly error messages
|
|
425
|
-
7. **Test different plans** - Monthly, annual, lifetime
|
|
426
|
-
|
|
427
|
-
## Related Hooks
|
|
428
|
-
|
|
429
|
-
- **useSubscription** - Basic subscription status
|
|
430
|
-
- **useSubscriptionStatus** - Detailed status
|
|
431
|
-
- **usePremium** - Simple premium check
|
|
432
|
-
- **useSubscriptionPackages** - Available packages
|
|
433
|
-
|
|
434
|
-
## See Also
|
|
435
|
-
|
|
436
|
-
- [useSubscriptionStatus](./useSubscriptionStatus.md)
|
|
437
|
-
- [Subscription Details Screen](../screens/README.md)
|
|
438
|
-
- [Package Utilities](../../../utils/README.md#package-utilities)
|
|
89
|
+
- **useSubscription**: Basic subscription status
|
|
90
|
+
- **useSubscriptionStatus**: Detailed status
|
|
91
|
+
- **usePremium**: Simple premium check
|
|
92
|
+
- **useSubscriptionPackages**: Available packages
|
|
93
|
+
- **Package Utilities**: `src/utils/README.md`
|