@umituz/react-native-subscription 2.14.97 → 2.14.98
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/LICENSE +21 -0
- package/README.md +462 -0
- package/package.json +1 -3
- package/src/application/README.md +229 -0
- package/src/application/ports/README.md +103 -0
- package/src/domain/README.md +402 -0
- package/src/domain/constants/README.md +80 -0
- package/src/domain/entities/README.md +176 -0
- package/src/domain/errors/README.md +307 -0
- package/src/domain/value-objects/README.md +186 -0
- package/src/domains/config/README.md +390 -0
- package/src/domains/paywall/README.md +371 -0
- package/src/domains/paywall/components/PaywallHeader.tsx +8 -11
- package/src/domains/paywall/components/README.md +185 -0
- package/src/domains/paywall/entities/README.md +199 -0
- package/src/domains/paywall/hooks/README.md +129 -0
- package/src/domains/wallet/README.md +292 -0
- package/src/domains/wallet/domain/README.md +108 -0
- package/src/domains/wallet/domain/entities/README.md +122 -0
- package/src/domains/wallet/domain/errors/README.md +157 -0
- package/src/domains/wallet/infrastructure/README.md +96 -0
- package/src/domains/wallet/presentation/components/BalanceCard.tsx +6 -12
- package/src/domains/wallet/presentation/components/README.md +231 -0
- package/src/domains/wallet/presentation/hooks/README.md +255 -0
- package/src/infrastructure/README.md +514 -0
- package/src/infrastructure/mappers/README.md +34 -0
- package/src/infrastructure/models/README.md +26 -0
- package/src/infrastructure/repositories/README.md +385 -0
- package/src/infrastructure/services/README.md +374 -0
- package/src/presentation/README.md +410 -0
- package/src/presentation/components/README.md +183 -0
- package/src/presentation/components/details/CreditRow.md +337 -0
- package/src/presentation/components/details/DetailRow.md +283 -0
- package/src/presentation/components/details/PremiumDetailsCard.md +266 -0
- package/src/presentation/components/details/PremiumStatusBadge.md +266 -0
- package/src/presentation/components/details/README.md +449 -0
- package/src/presentation/components/feedback/PaywallFeedbackModal.md +314 -0
- package/src/presentation/components/feedback/README.md +447 -0
- package/src/presentation/components/paywall/PaywallModal.md +444 -0
- package/src/presentation/components/paywall/README.md +190 -0
- package/src/presentation/components/sections/README.md +468 -0
- package/src/presentation/components/sections/SubscriptionSection.md +246 -0
- package/src/presentation/hooks/README.md +743 -0
- package/src/presentation/hooks/useAuthAwarePurchase.md +359 -0
- package/src/presentation/hooks/useAuthGate.md +403 -0
- package/src/presentation/hooks/useAuthSubscriptionSync.md +398 -0
- package/src/presentation/hooks/useCreditChecker.md +407 -0
- package/src/presentation/hooks/useCredits.md +342 -0
- package/src/presentation/hooks/useCreditsGate.md +346 -0
- package/src/presentation/hooks/useDeductCredit.md +160 -0
- package/src/presentation/hooks/useDevTestCallbacks.md +422 -0
- package/src/presentation/hooks/useFeatureGate.md +157 -0
- package/src/presentation/hooks/useInitializeCredits.md +458 -0
- package/src/presentation/hooks/usePaywall.md +334 -0
- package/src/presentation/hooks/usePaywallOperations.md +486 -0
- package/src/presentation/hooks/usePaywallVisibility.md +344 -0
- package/src/presentation/hooks/usePremium.md +230 -0
- package/src/presentation/hooks/usePremiumGate.md +423 -0
- package/src/presentation/hooks/usePremiumWithCredits.md +429 -0
- package/src/presentation/hooks/useSubscription.md +450 -0
- package/src/presentation/hooks/useSubscriptionDetails.md +438 -0
- package/src/presentation/hooks/useSubscriptionGate.md +168 -0
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +374 -0
- package/src/presentation/hooks/useSubscriptionStatus.md +424 -0
- package/src/presentation/hooks/useUserTier.md +356 -0
- package/src/presentation/hooks/useUserTierWithRepository.md +452 -0
- package/src/presentation/screens/README.md +194 -0
- package/src/presentation/types/README.md +38 -0
- package/src/presentation/utils/README.md +52 -0
- package/src/revenuecat/README.md +523 -0
- package/src/revenuecat/domain/README.md +147 -0
- package/src/revenuecat/domain/errors/README.md +197 -0
- package/src/revenuecat/infrastructure/config/README.md +40 -0
- package/src/revenuecat/infrastructure/managers/README.md +49 -0
- package/src/revenuecat/presentation/hooks/README.md +56 -0
- package/src/utils/README.md +529 -0
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
# usePremiumGate Hook
|
|
2
|
+
|
|
3
|
+
Feature gating hook for premium-only features with optional authentication.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { usePremiumGate } from '@umituz/react-native-subscription';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
function usePremiumGate(params: {
|
|
15
|
+
isPremium: boolean;
|
|
16
|
+
onPremiumRequired: () => void;
|
|
17
|
+
isAuthenticated?: boolean;
|
|
18
|
+
onAuthRequired?: () => void;
|
|
19
|
+
}): {
|
|
20
|
+
isPremium: boolean;
|
|
21
|
+
isAuthenticated: boolean;
|
|
22
|
+
requirePremium: (action: () => void) => void;
|
|
23
|
+
requireAuth: (action: () => void) => void;
|
|
24
|
+
requirePremiumWithAuth: (action: () => void) => void;
|
|
25
|
+
canAccess: boolean;
|
|
26
|
+
canAccessWithAuth: boolean;
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Parameters
|
|
31
|
+
|
|
32
|
+
| Parameter | Type | Default | Description |
|
|
33
|
+
|-----------|------|---------|-------------|
|
|
34
|
+
| `isPremium` | `boolean` | **Required** | Whether user has premium access |
|
|
35
|
+
| `onPremiumRequired` | `() => void` | **Required** | Callback when premium is required |
|
|
36
|
+
| `isAuthenticated` | `boolean` | `true` | Whether user is authenticated |
|
|
37
|
+
| `onAuthRequired` | `() => void` | `undefined` | Callback when auth is required |
|
|
38
|
+
|
|
39
|
+
## Returns
|
|
40
|
+
|
|
41
|
+
| Property | Type | Description |
|
|
42
|
+
|----------|------|-------------|
|
|
43
|
+
| `isPremium` | `boolean` | User has premium access |
|
|
44
|
+
| `isAuthenticated` | `boolean` | User is authenticated |
|
|
45
|
+
| `requirePremium` | `(action) => void` | Gate action behind premium |
|
|
46
|
+
| `requireAuth` | `(action) => void` | Gate action behind auth |
|
|
47
|
+
| `requirePremiumWithAuth` | `(action) => void` | Gate behind both auth and premium |
|
|
48
|
+
| `canAccess` | `boolean` | Can access premium feature |
|
|
49
|
+
| `canAccessWithAuth` | `boolean` | Can access (auth + premium) |
|
|
50
|
+
|
|
51
|
+
## Basic Usage
|
|
52
|
+
|
|
53
|
+
```typescript
|
|
54
|
+
function PremiumFeature() {
|
|
55
|
+
const { isPremium } = usePremium();
|
|
56
|
+
|
|
57
|
+
const { requirePremium, canAccess } = usePremiumGate({
|
|
58
|
+
isPremium,
|
|
59
|
+
onPremiumRequired: () => {
|
|
60
|
+
showPaywall();
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
const handleGenerate = () => {
|
|
65
|
+
requirePremium(() => {
|
|
66
|
+
// This only runs if user is premium
|
|
67
|
+
generatePremiumContent();
|
|
68
|
+
});
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<Button
|
|
73
|
+
onPress={handleGenerate}
|
|
74
|
+
disabled={!canAccess}
|
|
75
|
+
title={canAccess ? 'Generate' : 'Upgrade to Premium'}
|
|
76
|
+
/>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Advanced Usage
|
|
82
|
+
|
|
83
|
+
### With Authentication Check
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
function AuthenticatedPremiumFeature() {
|
|
87
|
+
const { isPremium } = usePremium();
|
|
88
|
+
const { user } = useAuth();
|
|
89
|
+
|
|
90
|
+
const { requirePremiumWithAuth, canAccessWithAuth } = usePremiumGate({
|
|
91
|
+
isPremium,
|
|
92
|
+
onPremiumRequired: () => showPaywall(),
|
|
93
|
+
isAuthenticated: !!user,
|
|
94
|
+
onAuthRequired: () => showAuthModal(),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
const handleAction = () => {
|
|
98
|
+
requirePremiumWithAuth(() => {
|
|
99
|
+
// Only runs if user is both authenticated AND premium
|
|
100
|
+
executeAction();
|
|
101
|
+
});
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<Button
|
|
106
|
+
onPress={handleAction}
|
|
107
|
+
disabled={!canAccessWithAuth}
|
|
108
|
+
title="Premium Action"
|
|
109
|
+
/>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### With Separate Gates
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
function MultiGateFeature() {
|
|
118
|
+
const { isPremium } = usePremium();
|
|
119
|
+
const { user } = useAuth();
|
|
120
|
+
|
|
121
|
+
const {
|
|
122
|
+
requirePremium,
|
|
123
|
+
requireAuth,
|
|
124
|
+
canAccess,
|
|
125
|
+
} = usePremiumGate({
|
|
126
|
+
isPremium,
|
|
127
|
+
onPremiumRequired: () => showPaywall(),
|
|
128
|
+
isAuthenticated: !!user,
|
|
129
|
+
onAuthRequired: () => showAuthModal(),
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<View>
|
|
134
|
+
<Button
|
|
135
|
+
onPress={() => requireAuth(() => saveToAccount())}
|
|
136
|
+
title="Save to Account (Auth required)"
|
|
137
|
+
/>
|
|
138
|
+
|
|
139
|
+
<Button
|
|
140
|
+
onPress={() => requirePremium(() => usePremiumFeature())}
|
|
141
|
+
title="Premium Feature (Premium required)"
|
|
142
|
+
/>
|
|
143
|
+
</View>
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### With Progressive Access
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
function ProgressiveAccess() {
|
|
152
|
+
const { isPremium } = usePremium();
|
|
153
|
+
const { user } = useAuth();
|
|
154
|
+
|
|
155
|
+
const {
|
|
156
|
+
isPremium: premium,
|
|
157
|
+
isAuthenticated: auth,
|
|
158
|
+
canAccess,
|
|
159
|
+
canAccessWithAuth,
|
|
160
|
+
} = usePremiumGate({
|
|
161
|
+
isPremium,
|
|
162
|
+
onPremiumRequired: () => showPaywall(),
|
|
163
|
+
isAuthenticated: !!user,
|
|
164
|
+
onAuthRequired: () => showAuthModal(),
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
const getAccessLevel = () => {
|
|
168
|
+
if (!auth) return 'guest';
|
|
169
|
+
if (!premium) return 'free';
|
|
170
|
+
return 'premium';
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
const accessLevel = getAccessLevel();
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
<View>
|
|
177
|
+
<Badge text={accessLevel} />
|
|
178
|
+
|
|
179
|
+
<FeatureList accessibleTo={['guest', 'free', 'premium']} />
|
|
180
|
+
<FeatureList accessibleTo={['free', 'premium']} />
|
|
181
|
+
<FeatureList accessibleTo={['premium']} />
|
|
182
|
+
</View>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### With Navigation Guard
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
function PremiumScreen() {
|
|
191
|
+
const { isPremium } = usePremium();
|
|
192
|
+
const navigation = useNavigation();
|
|
193
|
+
|
|
194
|
+
const { requirePremium } = usePremiumGate({
|
|
195
|
+
isPremium,
|
|
196
|
+
onPremiumRequired: () => {
|
|
197
|
+
navigation.replace('Paywall', {
|
|
198
|
+
returnTo: 'PremiumScreen',
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
// Redirect if not premium
|
|
205
|
+
requirePremium(() => {});
|
|
206
|
+
}, []);
|
|
207
|
+
|
|
208
|
+
if (!isPremium) return null;
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<View>
|
|
212
|
+
<Text>Premium Screen Content</Text>
|
|
213
|
+
</View>
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Examples
|
|
219
|
+
|
|
220
|
+
### Premium Button Component
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
function PremiumButton({
|
|
224
|
+
children,
|
|
225
|
+
onAction,
|
|
226
|
+
showUpgradeMessage = true,
|
|
227
|
+
}) {
|
|
228
|
+
const { isPremium } = usePremium();
|
|
229
|
+
|
|
230
|
+
const { requirePremium, canAccess } = usePremiumGate({
|
|
231
|
+
isPremium,
|
|
232
|
+
onPremiumRequired: () => {
|
|
233
|
+
if (showUpgradeMessage) {
|
|
234
|
+
Alert.alert(
|
|
235
|
+
'Premium Feature',
|
|
236
|
+
'This feature requires a Premium subscription',
|
|
237
|
+
[
|
|
238
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
239
|
+
{ text: 'Upgrade', onPress: () => navigation.navigate('Paywall') },
|
|
240
|
+
]
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
const handlePress = () => {
|
|
247
|
+
requirePremium(() => {
|
|
248
|
+
onAction?.();
|
|
249
|
+
});
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
return (
|
|
253
|
+
<TouchableOpacity
|
|
254
|
+
onPress={handlePress}
|
|
255
|
+
style={[styles.button, !canAccess && styles.lockedButton]}
|
|
256
|
+
disabled={!canAccess}
|
|
257
|
+
>
|
|
258
|
+
<PremiumIcon active={canAccess} />
|
|
259
|
+
<Text style={styles.text}>{children}</Text>
|
|
260
|
+
{!canAccess && <LockIcon />}
|
|
261
|
+
</TouchableOpacity>
|
|
262
|
+
);
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Batch Premium Operations
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
function BatchPremiumOperations({ items }) {
|
|
270
|
+
const { isPremium } = usePremium();
|
|
271
|
+
|
|
272
|
+
const { requirePremium } = usePremiumGate({
|
|
273
|
+
isPremium,
|
|
274
|
+
onPremiumRequired: () => {
|
|
275
|
+
showPaywall({
|
|
276
|
+
feature: 'Batch Operations',
|
|
277
|
+
highlight: `Process ${items.length} items at once`,
|
|
278
|
+
});
|
|
279
|
+
},
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
const handleBatchProcess = () => {
|
|
283
|
+
requirePremium(async () => {
|
|
284
|
+
for (const item of items) {
|
|
285
|
+
await processItem(item);
|
|
286
|
+
updateProgress();
|
|
287
|
+
}
|
|
288
|
+
Alert.alert('Complete', `Processed ${items.length} items`);
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
return (
|
|
293
|
+
<Button
|
|
294
|
+
onPress={handleBatchProcess}
|
|
295
|
+
title={`Process ${items.length} items`}
|
|
296
|
+
/>
|
|
297
|
+
);
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Conditional Rendering
|
|
302
|
+
|
|
303
|
+
```typescript
|
|
304
|
+
function ConditionalPremiumFeature() {
|
|
305
|
+
const { isPremium } = usePremium();
|
|
306
|
+
|
|
307
|
+
const { canAccess } = usePremiumGate({
|
|
308
|
+
isPremium,
|
|
309
|
+
onPremiumRequired: () => showPaywall(),
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
if (!canAccess) {
|
|
313
|
+
return (
|
|
314
|
+
<View style={styles.lockedContainer}>
|
|
315
|
+
<LockIcon size={48} />
|
|
316
|
+
<Text style={styles.title}>Premium Feature</Text>
|
|
317
|
+
<Text style={styles.message}>
|
|
318
|
+
Upgrade to access this feature
|
|
319
|
+
</Text>
|
|
320
|
+
<Button
|
|
321
|
+
onPress={() => showPaywall()}
|
|
322
|
+
title="Upgrade Now"
|
|
323
|
+
/>
|
|
324
|
+
</View>
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
return (
|
|
329
|
+
<View>
|
|
330
|
+
<Text>Premium Content</Text>
|
|
331
|
+
<PremiumFeatureComponent />
|
|
332
|
+
</View>
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### With Analytics
|
|
338
|
+
|
|
339
|
+
```typescript
|
|
340
|
+
function TrackedPremiumFeature() {
|
|
341
|
+
const { isPremium } = usePremium();
|
|
342
|
+
|
|
343
|
+
const { requirePremium } = usePremiumGate({
|
|
344
|
+
isPremium,
|
|
345
|
+
onPremiumRequired: () => {
|
|
346
|
+
analytics.track('premium_feature_accessed', {
|
|
347
|
+
feature: 'advanced_analytics',
|
|
348
|
+
success: false,
|
|
349
|
+
reason: 'not_premium',
|
|
350
|
+
});
|
|
351
|
+
showPaywall();
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
|
|
355
|
+
const handleFeature = () => {
|
|
356
|
+
requirePremium(() => {
|
|
357
|
+
analytics.track('premium_feature_used', {
|
|
358
|
+
feature: 'advanced_analytics',
|
|
359
|
+
success: true,
|
|
360
|
+
});
|
|
361
|
+
executeFeature();
|
|
362
|
+
});
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
return <Button onPress={handleFeature} title="Use Premium Feature" />;
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
## Best Practices
|
|
370
|
+
|
|
371
|
+
1. **Clear messaging** - Tell users what they're missing
|
|
372
|
+
2. **Smooth upgrades** - Make subscription path obvious
|
|
373
|
+
3. **Respect auth** - Check authentication before premium
|
|
374
|
+
4. **Track events** - Monitor gate triggers
|
|
375
|
+
5. **Value first** - Show benefits before locking
|
|
376
|
+
6. **Graceful fallbacks** - Show limited version if appropriate
|
|
377
|
+
7. **Context-aware** - Customize paywall based on feature
|
|
378
|
+
|
|
379
|
+
## Use Case Patterns
|
|
380
|
+
|
|
381
|
+
### Premium Only (No Auth)
|
|
382
|
+
|
|
383
|
+
```typescript
|
|
384
|
+
const { requirePremium } = usePremiumGate({
|
|
385
|
+
isPremium,
|
|
386
|
+
onPremiumRequired: () => showPaywall(),
|
|
387
|
+
});
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### Auth + Premium Required
|
|
391
|
+
|
|
392
|
+
```typescript
|
|
393
|
+
const { requirePremiumWithAuth } = usePremiumGate({
|
|
394
|
+
isPremium,
|
|
395
|
+
onPremiumRequired: () => showPaywall(),
|
|
396
|
+
isAuthenticated: !!user,
|
|
397
|
+
onAuthRequired: () => showAuthModal(),
|
|
398
|
+
});
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Separate Auth and Premium Gates
|
|
402
|
+
|
|
403
|
+
```typescript
|
|
404
|
+
const { requireAuth, requirePremium } = usePremiumGate({
|
|
405
|
+
isPremium,
|
|
406
|
+
onPremiumRequired: () => showPaywall(),
|
|
407
|
+
isAuthenticated: !!user,
|
|
408
|
+
onAuthRequired: () => showAuthModal(),
|
|
409
|
+
});
|
|
410
|
+
```
|
|
411
|
+
|
|
412
|
+
## Related Hooks
|
|
413
|
+
|
|
414
|
+
- **useAuthGate** - Authentication gating only
|
|
415
|
+
- **useSubscriptionGate** - Subscription gating
|
|
416
|
+
- **useFeatureGate** - Combined auth + subscription + credits
|
|
417
|
+
- **usePremium** - Premium status checking
|
|
418
|
+
|
|
419
|
+
## See Also
|
|
420
|
+
|
|
421
|
+
- [Premium Gating](../../../docs/PREMIUM_GATING.md)
|
|
422
|
+
- [Feature Access Patterns](../../../docs/ACCESS_PATTERNS.md)
|
|
423
|
+
- [Paywall Triggers](../screens/README.md#triggers)
|