@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,429 @@
|
|
|
1
|
+
# usePremiumWithCredits Hook
|
|
2
|
+
|
|
3
|
+
Combined hook for premium subscription with credits system integration.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { usePremiumWithCredits } from '@umituz/react-native-subscription';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
function usePremiumWithCredits(params: {
|
|
15
|
+
userId: string | undefined;
|
|
16
|
+
isPremium: boolean;
|
|
17
|
+
}): {
|
|
18
|
+
credits: number;
|
|
19
|
+
balance: number;
|
|
20
|
+
transactions: Transaction[];
|
|
21
|
+
isLoading: boolean;
|
|
22
|
+
error: Error | null;
|
|
23
|
+
refetch: () => Promise<void>;
|
|
24
|
+
ensureCreditsInitialized: () => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Parameters
|
|
29
|
+
|
|
30
|
+
| Parameter | Type | Default | Description |
|
|
31
|
+
|-----------|------|---------|-------------|
|
|
32
|
+
| `userId` | `string \| undefined` | **Required** | User ID |
|
|
33
|
+
| `isPremium` | `boolean` | **Required** | Whether user has premium subscription |
|
|
34
|
+
|
|
35
|
+
## Returns
|
|
36
|
+
|
|
37
|
+
Returns all properties from `useCredits` plus:
|
|
38
|
+
|
|
39
|
+
| Property | Type | Description |
|
|
40
|
+
|----------|------|-------------|
|
|
41
|
+
| `ensureCreditsInitialized` | `() => Promise<void>` | Ensure credits are initialized |
|
|
42
|
+
|
|
43
|
+
## Basic Usage
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
function PremiumUserDashboard() {
|
|
47
|
+
const { user } = useAuth();
|
|
48
|
+
const { isPremium } = usePremium();
|
|
49
|
+
|
|
50
|
+
const { credits, isLoading, ensureCreditsInitialized } = usePremiumWithCredits({
|
|
51
|
+
userId: user?.uid,
|
|
52
|
+
isPremium,
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
if (isPremium) {
|
|
57
|
+
ensureCreditsInitialized();
|
|
58
|
+
}
|
|
59
|
+
}, [isPremium]);
|
|
60
|
+
|
|
61
|
+
if (isLoading) return <ActivityIndicator />;
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<View>
|
|
65
|
+
<Text>Credits: {credits}</Text>
|
|
66
|
+
<Text>Status: {isPremium ? 'Premium' : 'Free'}</Text>
|
|
67
|
+
</View>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Advanced Usage
|
|
73
|
+
|
|
74
|
+
### With Auto-Initialization
|
|
75
|
+
|
|
76
|
+
```typescript
|
|
77
|
+
function PremiumCreditsManager() {
|
|
78
|
+
const { user } = useAuth();
|
|
79
|
+
const { isPremium } = usePremium();
|
|
80
|
+
|
|
81
|
+
const {
|
|
82
|
+
credits,
|
|
83
|
+
transactions,
|
|
84
|
+
isLoading,
|
|
85
|
+
ensureCreditsInitialized,
|
|
86
|
+
} = usePremiumWithCredits({
|
|
87
|
+
userId: user?.uid,
|
|
88
|
+
isPremium,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
// Hook automatically initializes credits when user becomes premium
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (isPremium && !credits) {
|
|
94
|
+
console.log('User is premium but has no credits, initializing...');
|
|
95
|
+
ensureCreditsInitialized();
|
|
96
|
+
}
|
|
97
|
+
}, [isPremium, credits]);
|
|
98
|
+
|
|
99
|
+
if (isLoading) return <LoadingScreen />;
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<View>
|
|
103
|
+
<CreditBalance credits={credits} />
|
|
104
|
+
<TransactionHistory transactions={transactions} />
|
|
105
|
+
</View>
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### With Subscription Change Detection
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
function SubscriptionWatcher() {
|
|
114
|
+
const { user } = useAuth();
|
|
115
|
+
const { isPremium } = usePremium();
|
|
116
|
+
|
|
117
|
+
const { credits, ensureCreditsInitialized } = usePremiumWithCredits({
|
|
118
|
+
userId: user?.uid,
|
|
119
|
+
isPremium,
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
const previousPremium = useRef(isPremium);
|
|
123
|
+
|
|
124
|
+
useEffect(() => {
|
|
125
|
+
// User just subscribed
|
|
126
|
+
if (isPremium && !previousPremium.current) {
|
|
127
|
+
console.log('User subscribed to premium!');
|
|
128
|
+
ensureCreditsInitialized();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
previousPremium.current = isPremium;
|
|
132
|
+
}, [isPremium]);
|
|
133
|
+
|
|
134
|
+
return (
|
|
135
|
+
<View>
|
|
136
|
+
<Text>Status: {isPremium ? 'Premium' : 'Free'}</Text>
|
|
137
|
+
<Text>Credits: {credits || 0}</Text>
|
|
138
|
+
</View>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### With Manual Initialization
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
function ManualCreditInit() {
|
|
147
|
+
const { user } = useAuth();
|
|
148
|
+
const { isPremium } = usePremium();
|
|
149
|
+
|
|
150
|
+
const { credits, isLoading, ensureCreditsInitialized } = usePremiumWithCredits({
|
|
151
|
+
userId: user?.uid,
|
|
152
|
+
isPremium,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const handleInitializeCredits = async () => {
|
|
156
|
+
if (!isPremium) {
|
|
157
|
+
Alert.alert('Premium Required', 'This feature requires a subscription');
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (credits) {
|
|
162
|
+
Alert.alert('Already Initialized', 'Credits are already set up');
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
await ensureCreditsInitialized();
|
|
167
|
+
Alert.alert('Success', 'Credits initialized successfully');
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
return (
|
|
171
|
+
<View>
|
|
172
|
+
<Text>Credits: {credits || 'Not initialized'}</Text>
|
|
173
|
+
|
|
174
|
+
{!credits && isPremium && (
|
|
175
|
+
<Button
|
|
176
|
+
onPress={handleInitializeCredits}
|
|
177
|
+
disabled={isLoading}
|
|
178
|
+
title="Initialize Credits"
|
|
179
|
+
/>
|
|
180
|
+
)}
|
|
181
|
+
</View>
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### With Error Handling
|
|
187
|
+
|
|
188
|
+
```typescript
|
|
189
|
+
function RobustCreditManager() {
|
|
190
|
+
const { user } = useAuth();
|
|
191
|
+
const { isPremium } = usePremium();
|
|
192
|
+
|
|
193
|
+
const {
|
|
194
|
+
credits,
|
|
195
|
+
error,
|
|
196
|
+
isLoading,
|
|
197
|
+
ensureCreditsInitialized,
|
|
198
|
+
} = usePremiumWithCredits({
|
|
199
|
+
userId: user?.uid,
|
|
200
|
+
isPremium,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
useEffect(() => {
|
|
204
|
+
if (error) {
|
|
205
|
+
console.error('Credits error:', error);
|
|
206
|
+
Alert.alert('Error', 'Failed to load credits');
|
|
207
|
+
}
|
|
208
|
+
}, [error]);
|
|
209
|
+
|
|
210
|
+
const handleRetry = async () => {
|
|
211
|
+
try {
|
|
212
|
+
await ensureCreditsInitialized();
|
|
213
|
+
} catch (err) {
|
|
214
|
+
Alert.alert('Error', 'Failed to initialize credits');
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
if (isLoading) return <LoadingScreen />;
|
|
219
|
+
|
|
220
|
+
return (
|
|
221
|
+
<View>
|
|
222
|
+
<Text>Credits: {credits || 0}</Text>
|
|
223
|
+
|
|
224
|
+
{error && (
|
|
225
|
+
<Button onPress={handleRetry} title="Retry" />
|
|
226
|
+
)}
|
|
227
|
+
</View>
|
|
228
|
+
);
|
|
229
|
+
}
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## Examples
|
|
233
|
+
|
|
234
|
+
### Premium Onboarding Flow
|
|
235
|
+
|
|
236
|
+
```typescript
|
|
237
|
+
function PremiumOnboarding() {
|
|
238
|
+
const { user } = useAuth();
|
|
239
|
+
const { isPremium } = usePremium();
|
|
240
|
+
|
|
241
|
+
const {
|
|
242
|
+
credits,
|
|
243
|
+
isLoading,
|
|
244
|
+
ensureCreditsInitialized,
|
|
245
|
+
} = usePremiumWithCredits({
|
|
246
|
+
userId: user?.uid,
|
|
247
|
+
isPremium,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
useEffect(() => {
|
|
251
|
+
// Auto-initialize credits for new premium users
|
|
252
|
+
if (isPremium && !credits && !isLoading) {
|
|
253
|
+
const initialize = async () => {
|
|
254
|
+
await ensureCreditsInitialized();
|
|
255
|
+
analytics.track('premium_credits_initialized', {
|
|
256
|
+
userId: user?.uid,
|
|
257
|
+
});
|
|
258
|
+
};
|
|
259
|
+
initialize();
|
|
260
|
+
}
|
|
261
|
+
}, [isPremium, credits, isLoading]);
|
|
262
|
+
|
|
263
|
+
if (!isPremium) {
|
|
264
|
+
return <PremiumUpgradePrompt />;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (isLoading) {
|
|
268
|
+
return <LoadingScreen message="Setting up your account..." />;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
return (
|
|
272
|
+
<View>
|
|
273
|
+
<CongratulationsMessage />
|
|
274
|
+
|
|
275
|
+
<CreditCard credits={credits} />
|
|
276
|
+
|
|
277
|
+
<Button
|
|
278
|
+
onPress={() => navigation.navigate('Home')}
|
|
279
|
+
title="Get Started"
|
|
280
|
+
/>
|
|
281
|
+
</View>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Premium Benefits Display
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
function PremiumBenefits() {
|
|
290
|
+
const { user } = useAuth();
|
|
291
|
+
const { isPremium } = usePremium();
|
|
292
|
+
|
|
293
|
+
const { credits, balance, transactions } = usePremiumWithCredits({
|
|
294
|
+
userId: user?.uid,
|
|
295
|
+
isPremium,
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
return (
|
|
299
|
+
<ScrollView>
|
|
300
|
+
<PremiumBadge />
|
|
301
|
+
|
|
302
|
+
<View style={styles.section}>
|
|
303
|
+
<Text style={styles.title}>Your Premium Benefits</Text>
|
|
304
|
+
<BenefitItem icon="✓" text="Ad-free experience" />
|
|
305
|
+
<BenefitItem icon="✓" text="Unlimited access" />
|
|
306
|
+
<BenefitItem icon="✓" text={`${credits} monthly credits`} />
|
|
307
|
+
<BenefitItem icon="✓" text="Priority support" />
|
|
308
|
+
</View>
|
|
309
|
+
|
|
310
|
+
<View style={styles.section}>
|
|
311
|
+
<Text style={styles.title}>Credit Balance</Text>
|
|
312
|
+
<Text style={styles.balance}>{credits} Credits</Text>
|
|
313
|
+
<Text style={styles.value}>Worth ~${balance.toFixed(2)}</Text>
|
|
314
|
+
</View>
|
|
315
|
+
|
|
316
|
+
<View style={styles.section}>
|
|
317
|
+
<Text style={styles.title}>Recent Activity</Text>
|
|
318
|
+
{transactions.slice(0, 5).map((tx) => (
|
|
319
|
+
<TransactionItem key={tx.id} transaction={tx} />
|
|
320
|
+
))}
|
|
321
|
+
</View>
|
|
322
|
+
</ScrollView>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Subscription Status Monitor
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
function SubscriptionMonitor() {
|
|
331
|
+
const { user } = useAuth();
|
|
332
|
+
const { isPremium } = usePremium();
|
|
333
|
+
|
|
334
|
+
const {
|
|
335
|
+
credits,
|
|
336
|
+
isLoading,
|
|
337
|
+
ensureCreditsInitialized,
|
|
338
|
+
} = usePremiumWithCredits({
|
|
339
|
+
userId: user?.uid,
|
|
340
|
+
isPremium,
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
const [lastChecked, setLastChecked] = useState<Date | null>(null);
|
|
344
|
+
|
|
345
|
+
const handleRefresh = async () => {
|
|
346
|
+
await ensureCreditsInitialized();
|
|
347
|
+
setLastChecked(new Date());
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
useEffect(() => {
|
|
351
|
+
// Periodic refresh every 5 minutes
|
|
352
|
+
const interval = setInterval(() => {
|
|
353
|
+
if (isPremium) {
|
|
354
|
+
handleRefresh();
|
|
355
|
+
}
|
|
356
|
+
}, 5 * 60 * 1000);
|
|
357
|
+
|
|
358
|
+
return () => clearInterval(interval);
|
|
359
|
+
}, [isPremium]);
|
|
360
|
+
|
|
361
|
+
return (
|
|
362
|
+
<View>
|
|
363
|
+
<Text>Subscription Status: {isPremium ? 'Active' : 'Inactive'}</Text>
|
|
364
|
+
<Text>Credits: {credits || 0}</Text>
|
|
365
|
+
{lastChecked && (
|
|
366
|
+
<Text>Last checked: {lastChecked.toLocaleTimeString()}</Text>
|
|
367
|
+
)}
|
|
368
|
+
|
|
369
|
+
<Button
|
|
370
|
+
onPress={handleRefresh}
|
|
371
|
+
disabled={isLoading}
|
|
372
|
+
title="Refresh Status"
|
|
373
|
+
/>
|
|
374
|
+
</View>
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
## How It Works
|
|
380
|
+
|
|
381
|
+
### Automatic Initialization
|
|
382
|
+
|
|
383
|
+
The hook automatically:
|
|
384
|
+
|
|
385
|
+
1. **Detects premium status** - Checks if user is premium
|
|
386
|
+
2. **Monitors credits** - Watches credits value
|
|
387
|
+
3. **Initializes when needed** - Calls init if premium but no credits
|
|
388
|
+
4. **Prevents duplicate inits** - Won't initialize if credits exist
|
|
389
|
+
5. **Handles loading** - Shows loading state during initialization
|
|
390
|
+
|
|
391
|
+
```typescript
|
|
392
|
+
// Premium user without credits
|
|
393
|
+
isPremium = true
|
|
394
|
+
credits = undefined
|
|
395
|
+
→ Auto-initializes credits ✅
|
|
396
|
+
|
|
397
|
+
// Premium user with credits
|
|
398
|
+
isPremium = true
|
|
399
|
+
credits = 100
|
|
400
|
+
→ No initialization needed ✅
|
|
401
|
+
|
|
402
|
+
// Free user
|
|
403
|
+
isPremium = false
|
|
404
|
+
credits = undefined
|
|
405
|
+
→ No initialization (not premium) ✅
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
## Best Practices
|
|
409
|
+
|
|
410
|
+
1. **Trust the hook** - Let it handle auto-initialization
|
|
411
|
+
2. **Monitor loading** - Show loading during initialization
|
|
412
|
+
3. **Handle errors** - Catch and display init failures
|
|
413
|
+
4. **Track events** - Log credit initialization
|
|
414
|
+
5. **Refresh periodically** - Keep credits up to date
|
|
415
|
+
6. **Check premium first** - Verify user is premium before showing features
|
|
416
|
+
7. **Test scenarios** - Test new subscription, existing subscription, cancellation
|
|
417
|
+
|
|
418
|
+
## Related Hooks
|
|
419
|
+
|
|
420
|
+
- **useCredits** - Credits management
|
|
421
|
+
- **useInitializeCredits** - Manual credit initialization
|
|
422
|
+
- **usePremium** - Premium status
|
|
423
|
+
- **useDeductCredit** - Credit deduction
|
|
424
|
+
|
|
425
|
+
## See Also
|
|
426
|
+
|
|
427
|
+
- [Credits System](../../../domains/wallet/README.md)
|
|
428
|
+
- [Premium Integration](../../../docs/PREMIUM_INTEGRATION.md)
|
|
429
|
+
- [Credits README](./useCredits.md)
|