@umituz/react-native-subscription 2.14.96 → 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 +3 -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/revenuecat/presentation/hooks/usePurchasePackage.ts +1 -1
- package/src/utils/README.md +529 -0
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# usePaywall Hook
|
|
2
|
+
|
|
3
|
+
Hook for controlling paywall visibility and state.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { usePaywall } from '@umituz/react-native-subscription';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
function usePaywall(): {
|
|
15
|
+
showPaywall: (params?: PaywallTrigger) => void;
|
|
16
|
+
hidePaywall: () => void;
|
|
17
|
+
isPaywallVisible: boolean;
|
|
18
|
+
paywallConfig: PaywallConfig | null;
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Returns
|
|
23
|
+
|
|
24
|
+
| Property | Type | Description |
|
|
25
|
+
|----------|------|-------------|
|
|
26
|
+
| `showPaywall` | `(params?: PaywallTrigger) => void` | Show paywall with optional context |
|
|
27
|
+
| `hidePaywall` | `() => void` | Hide paywall |
|
|
28
|
+
| `isPaywallVisible` | `boolean` | Whether paywall is currently visible |
|
|
29
|
+
| `paywallConfig` | `PaywallConfig \| null` | Current paywall configuration |
|
|
30
|
+
|
|
31
|
+
## Basic Usage
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
function UpgradeButton() {
|
|
35
|
+
const { showPaywall, hidePaywall, isPaywallVisible } = usePaywall();
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<>
|
|
39
|
+
<Button
|
|
40
|
+
onPress={() => showPaywall()}
|
|
41
|
+
title="Upgrade to Premium"
|
|
42
|
+
/>
|
|
43
|
+
|
|
44
|
+
<PaywallModal
|
|
45
|
+
isVisible={isPaywallVisible}
|
|
46
|
+
onClose={hidePaywall}
|
|
47
|
+
/>
|
|
48
|
+
</>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Advanced Usage
|
|
54
|
+
|
|
55
|
+
### With Trigger Tracking
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
function TrackedPaywall() {
|
|
59
|
+
const { showPaywall, hidePaywall, isPaywallVisible } = usePaywall();
|
|
60
|
+
|
|
61
|
+
const handleUpgradeClick = (source: string) => {
|
|
62
|
+
showPaywall({
|
|
63
|
+
trigger: 'upgrade_button',
|
|
64
|
+
featureId: 'advanced_features',
|
|
65
|
+
source,
|
|
66
|
+
metadata: {
|
|
67
|
+
screen: 'home',
|
|
68
|
+
buttonLocation: 'header',
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
// Analytics
|
|
73
|
+
analytics.track('upgrade_button_clicked', { source });
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const handleClose = () => {
|
|
77
|
+
analytics.track('paywall_dismissed', {
|
|
78
|
+
trigger: 'upgrade_button',
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
hidePaywall();
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
return (
|
|
85
|
+
<>
|
|
86
|
+
<Button onPress={() => handleUpgradeClick('header')} title="Upgrade" />
|
|
87
|
+
|
|
88
|
+
<PaywallModal
|
|
89
|
+
isVisible={isPaywallVisible}
|
|
90
|
+
onClose={handleClose}
|
|
91
|
+
/>
|
|
92
|
+
</>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### With Dynamic Config
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
function DynamicPaywall() {
|
|
101
|
+
const { showPaywall, hidePaywall, isPaywallVisible, paywallConfig } =
|
|
102
|
+
usePaywall();
|
|
103
|
+
|
|
104
|
+
const customizePaywall = (tier: 'free' | 'premium') => {
|
|
105
|
+
showPaywall({
|
|
106
|
+
trigger: 'custom',
|
|
107
|
+
config: {
|
|
108
|
+
title: tier === 'free'
|
|
109
|
+
? 'Unlock Premium Features'
|
|
110
|
+
: 'Upgrade Your Plan',
|
|
111
|
+
features: tier === 'free'
|
|
112
|
+
? [
|
|
113
|
+
{ icon: '⭐', text: 'Unlimited Access' },
|
|
114
|
+
{ icon: '🚀', text: 'AI-Powered Tools' },
|
|
115
|
+
]
|
|
116
|
+
: [
|
|
117
|
+
{ icon: '💎', text: 'Exclusive Features' },
|
|
118
|
+
{ icon: '👑', text: 'VIP Support' },
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
return (
|
|
125
|
+
<View>
|
|
126
|
+
<Button onPress={() => customizePaywall('free')} title="Show Free Paywall" />
|
|
127
|
+
<Button onPress={() => customizePaywall('premium')} title="Show Premium Paywall" />
|
|
128
|
+
|
|
129
|
+
<PaywallModal
|
|
130
|
+
isVisible={isPaywallVisible}
|
|
131
|
+
onClose={hidePaywall}
|
|
132
|
+
config={paywallConfig || undefined}
|
|
133
|
+
/>
|
|
134
|
+
</View>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### With Context-Aware Display
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
function ContextAwarePaywall() {
|
|
143
|
+
const { showPaywall, hidePaywall, isPaywallVisible } = usePaywall();
|
|
144
|
+
const { userTier } = useUserTier();
|
|
145
|
+
const { usageCount } = useFeatureUsage();
|
|
146
|
+
|
|
147
|
+
const shouldShowPaywall = useMemo(() => {
|
|
148
|
+
// Show paywall after 5 free uses
|
|
149
|
+
return userTier === 'free' && usageCount >= 5;
|
|
150
|
+
}, [userTier, usageCount]);
|
|
151
|
+
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (shouldShowPaywall && !isPaywallVisible) {
|
|
154
|
+
showPaywall({
|
|
155
|
+
trigger: 'usage_limit',
|
|
156
|
+
featureId: 'advanced_filters',
|
|
157
|
+
context: {
|
|
158
|
+
usageCount,
|
|
159
|
+
limit: 5,
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}, [shouldShowPaywall]);
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<PaywallModal
|
|
167
|
+
isVisible={isPaywallVisible}
|
|
168
|
+
onClose={hidePaywall}
|
|
169
|
+
config={{
|
|
170
|
+
title: 'Free Limit Reached',
|
|
171
|
+
description: `You've used this feature ${usageCount} times`,
|
|
172
|
+
features: [
|
|
173
|
+
{ icon: '∞', text: 'Unlimited Access' },
|
|
174
|
+
{ icon: '⚡', text: 'Faster Processing' },
|
|
175
|
+
],
|
|
176
|
+
}}
|
|
177
|
+
/>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## PaywallTrigger Type
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
interface PaywallTrigger {
|
|
186
|
+
trigger: string; // What triggered the paywall
|
|
187
|
+
featureId?: string; // Which feature triggered it
|
|
188
|
+
source?: string; // Where it was triggered from
|
|
189
|
+
metadata?: Record<string, any>; // Additional context
|
|
190
|
+
config?: PaywallConfig; // Custom paywall config
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Examples
|
|
195
|
+
|
|
196
|
+
### Feature-Based Paywall
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
function FeatureButton({ featureId, requiredTier }) {
|
|
200
|
+
const { userTier } = useUserTier();
|
|
201
|
+
const { showPaywall } = usePaywall();
|
|
202
|
+
|
|
203
|
+
const handlePress = () => {
|
|
204
|
+
if (userTier !== requiredTier) {
|
|
205
|
+
showPaywall({
|
|
206
|
+
trigger: 'feature_access_denied',
|
|
207
|
+
featureId,
|
|
208
|
+
requiredTier,
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
executeFeature();
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
return <Button onPress={handlePress} title={featureId} />;
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### Time-Based Paywall
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
function TimedPaywall() {
|
|
224
|
+
const { showPaywall, isPaywallVisible } = usePaywall();
|
|
225
|
+
const [sessionTime, setSessionTime] = useState(0);
|
|
226
|
+
|
|
227
|
+
useEffect(() => {
|
|
228
|
+
const timer = setInterval(() => {
|
|
229
|
+
setSessionTime(prev => prev + 1);
|
|
230
|
+
}, 1000);
|
|
231
|
+
|
|
232
|
+
// Show paywall after 30 seconds
|
|
233
|
+
const paywallTimer = setTimeout(() => {
|
|
234
|
+
showPaywall({
|
|
235
|
+
trigger: 'time_based',
|
|
236
|
+
context: { sessionTime },
|
|
237
|
+
});
|
|
238
|
+
}, 30000);
|
|
239
|
+
|
|
240
|
+
return () => {
|
|
241
|
+
clearInterval(timer);
|
|
242
|
+
clearTimeout(paywallTimer);
|
|
243
|
+
};
|
|
244
|
+
}, []);
|
|
245
|
+
|
|
246
|
+
return <PaywallModal isVisible={isPaywallVisible} onClose={() => {}} />;
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Event-Based Paywall
|
|
251
|
+
|
|
252
|
+
```typescript
|
|
253
|
+
function EventDrivenPaywall() {
|
|
254
|
+
const { showPaywall, isPaywallVisible } = usePaywall();
|
|
255
|
+
|
|
256
|
+
useEffect(() => {
|
|
257
|
+
const subscription = eventBus.subscribe('premium_required', (event) => {
|
|
258
|
+
showPaywall({
|
|
259
|
+
trigger: 'premium_required',
|
|
260
|
+
featureId: event.featureId,
|
|
261
|
+
source: event.source,
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
return () => subscription.unsubscribe();
|
|
266
|
+
}, []);
|
|
267
|
+
|
|
268
|
+
return <PaywallModal isVisible={isPaywallVisible} onClose={() => {}} />;
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## Integration with Analytics
|
|
273
|
+
|
|
274
|
+
```typescript
|
|
275
|
+
function AnalyticsIntegratedPaywall() {
|
|
276
|
+
const { showPaywall, hidePaywall, isPaywallVisible } = usePaywall();
|
|
277
|
+
const [paywallShownAt, setPaywallShownAt] = useState<number | null>(null);
|
|
278
|
+
|
|
279
|
+
const handleShowPaywall = (trigger: PaywallTrigger) => {
|
|
280
|
+
setPaywallShownAt(Date.now());
|
|
281
|
+
|
|
282
|
+
// Track impression
|
|
283
|
+
analytics.track('paywall_impression', {
|
|
284
|
+
trigger: trigger.trigger,
|
|
285
|
+
feature_id: trigger.featureId,
|
|
286
|
+
source: trigger.source,
|
|
287
|
+
timestamp: Date.now(),
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
showPaywall(trigger);
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
const handleClose = () => {
|
|
294
|
+
if (paywallShownAt) {
|
|
295
|
+
const duration = Date.now() - paywallShownAt;
|
|
296
|
+
|
|
297
|
+
analytics.track('paywall_dismissed', {
|
|
298
|
+
duration,
|
|
299
|
+
trigger: 'upgrade_button',
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
hidePaywall();
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
return (
|
|
307
|
+
<>
|
|
308
|
+
<Button onPress={() => handleShowPaywall({ trigger: 'manual' })} />
|
|
309
|
+
<PaywallModal isVisible={isPaywallVisible} onClose={handleClose} />
|
|
310
|
+
</>
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
## Best Practices
|
|
316
|
+
|
|
317
|
+
1. **Track triggers** - Always log what triggered the paywall
|
|
318
|
+
2. **Include context** - Add relevant metadata
|
|
319
|
+
3. **Handle dismissal** - Track when and why users close
|
|
320
|
+
4. **A/B test** - Test different paywall configurations
|
|
321
|
+
5. **Respect users** - Don't show paywall too frequently
|
|
322
|
+
6. **Close on purchase** - Automatically hide on successful purchase
|
|
323
|
+
|
|
324
|
+
## Related Hooks
|
|
325
|
+
|
|
326
|
+
- **usePaywallActions** - For paywall purchase actions
|
|
327
|
+
- **usePaywallVisibility** - For conditional paywall display
|
|
328
|
+
- **usePaywallOperations** - For complete paywall operations
|
|
329
|
+
|
|
330
|
+
## See Also
|
|
331
|
+
|
|
332
|
+
- [usePaywallActions](./usePaywallActions.md)
|
|
333
|
+
- [usePaywallVisibility](./usePaywallVisibility.md)
|
|
334
|
+
- [Paywall Domain](../../../domains/paywall/README.md)
|