@umituz/react-native-subscription 2.14.97 → 2.14.99
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 +461 -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/README.md +240 -0
- package/src/domains/config/README.md +390 -0
- package/src/domains/config/domain/README.md +390 -0
- package/src/domains/config/domain/entities/README.md +350 -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 +176 -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/application/README.md +158 -0
- package/src/revenuecat/application/ports/README.md +169 -0
- package/src/revenuecat/domain/README.md +147 -0
- package/src/revenuecat/domain/constants/README.md +183 -0
- package/src/revenuecat/domain/entities/README.md +382 -0
- package/src/revenuecat/domain/errors/README.md +197 -0
- package/src/revenuecat/domain/types/README.md +373 -0
- package/src/revenuecat/domain/value-objects/README.md +441 -0
- package/src/revenuecat/infrastructure/README.md +50 -0
- package/src/revenuecat/infrastructure/config/README.md +40 -0
- package/src/revenuecat/infrastructure/handlers/README.md +218 -0
- package/src/revenuecat/infrastructure/managers/README.md +49 -0
- package/src/revenuecat/infrastructure/services/README.md +325 -0
- package/src/revenuecat/infrastructure/utils/README.md +382 -0
- package/src/revenuecat/presentation/README.md +184 -0
- package/src/revenuecat/presentation/hooks/README.md +56 -0
- package/src/utils/README.md +529 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
# useCreditChecker Hook
|
|
2
|
+
|
|
3
|
+
Provides credit checking utilities with dedicated repository integration.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { useCreditChecker } from '@umituz/react-native-subscription';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
function useCreditChecker(params?: {
|
|
15
|
+
onCreditDeducted?: (userId: string, cost: number) => void;
|
|
16
|
+
}): {
|
|
17
|
+
checkCreditsAvailable: (
|
|
18
|
+
userId: string | undefined,
|
|
19
|
+
cost?: number
|
|
20
|
+
) => Promise<CreditCheckResult>;
|
|
21
|
+
deductCreditsAfterSuccess: (
|
|
22
|
+
userId: string | undefined,
|
|
23
|
+
cost?: number
|
|
24
|
+
) => Promise<void>;
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Parameters
|
|
29
|
+
|
|
30
|
+
| Parameter | Type | Default | Description |
|
|
31
|
+
|-----------|------|---------|-------------|
|
|
32
|
+
| `onCreditDeducted` | `(userId, cost) => void` | `undefined` | Callback after successful deduction |
|
|
33
|
+
|
|
34
|
+
## Returns
|
|
35
|
+
|
|
36
|
+
| Property | Type | Description |
|
|
37
|
+
|----------|------|-------------|
|
|
38
|
+
| `checkCreditsAvailable` | `(userId, cost?) => Promise<CreditCheckResult>` | Check if user has enough credits |
|
|
39
|
+
| `deductCreditsAfterSuccess` | `(userId, cost?) => Promise<void>` | Deduct after successful operation |
|
|
40
|
+
|
|
41
|
+
## CreditCheckResult
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
interface CreditCheckResult {
|
|
45
|
+
hasCredits: boolean;
|
|
46
|
+
currentBalance: number;
|
|
47
|
+
required: number;
|
|
48
|
+
canProceed: boolean;
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Basic Usage
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
function CreditFeature() {
|
|
56
|
+
const { user } = useAuth();
|
|
57
|
+
const { checkCreditsAvailable } = useCreditChecker();
|
|
58
|
+
|
|
59
|
+
const handleUseFeature = async () => {
|
|
60
|
+
const result = await checkCreditsAvailable(user?.uid, 5);
|
|
61
|
+
|
|
62
|
+
if (!result.canProceed) {
|
|
63
|
+
Alert.alert(
|
|
64
|
+
'Insufficient Credits',
|
|
65
|
+
`You need ${result.required} credits but only have ${result.currentBalance}`
|
|
66
|
+
);
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Proceed with feature
|
|
71
|
+
await executeFeature();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
return <Button onPress={handleUseFeature} title="Use Feature (5 credits)" />;
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## Advanced Usage
|
|
79
|
+
|
|
80
|
+
### With Deduction Callback
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
function CreditWithCallback() {
|
|
84
|
+
const { user } = useAuth();
|
|
85
|
+
|
|
86
|
+
const { checkCreditsAvailable } = useCreditChecker({
|
|
87
|
+
onCreditDeducted: (userId, cost) => {
|
|
88
|
+
console.log(`Deducted ${cost} credits from ${userId}`);
|
|
89
|
+
analytics.track('credits_deducted', { userId, cost });
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const handleAction = async () => {
|
|
94
|
+
const result = await checkCreditsAvailable(user?.uid, 3);
|
|
95
|
+
|
|
96
|
+
if (!result.canProceed) {
|
|
97
|
+
showPaywall();
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await performAction();
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
return <Button onPress={handleAction} title="Execute (3 credits)" />;
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
### With Two-Step Process
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
function TwoStepCreditProcess() {
|
|
112
|
+
const { user } = useAuth();
|
|
113
|
+
|
|
114
|
+
const {
|
|
115
|
+
checkCreditsAvailable,
|
|
116
|
+
deductCreditsAfterSuccess,
|
|
117
|
+
} = useCreditChecker();
|
|
118
|
+
|
|
119
|
+
const handleProcess = async () => {
|
|
120
|
+
// Step 1: Check credits
|
|
121
|
+
const check = await checkCreditsAvailable(user?.uid, 10);
|
|
122
|
+
|
|
123
|
+
if (!check.canProceed) {
|
|
124
|
+
Alert.alert('Insufficient Credits', 'You need 10 credits for this operation');
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
// Step 2: Perform operation
|
|
130
|
+
const result = await expensiveOperation();
|
|
131
|
+
|
|
132
|
+
// Step 3: Deduct credits only after success
|
|
133
|
+
await deductCreditsAfterSuccess(user?.uid, 10);
|
|
134
|
+
|
|
135
|
+
Alert.alert('Success', 'Operation completed!');
|
|
136
|
+
} catch (error) {
|
|
137
|
+
Alert.alert('Error', 'Operation failed, credits not deducted');
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
return <Button onPress={handleProcess} title="Process (10 credits)" />;
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### With Pre-Check UI
|
|
146
|
+
|
|
147
|
+
```typescript
|
|
148
|
+
function CreditPreCheck() {
|
|
149
|
+
const { user } = useAuth();
|
|
150
|
+
const { checkCreditsAvailable } = useCreditChecker();
|
|
151
|
+
|
|
152
|
+
const [creditCheck, setCreditCheck] = useState<CreditCheckResult | null>(null);
|
|
153
|
+
|
|
154
|
+
useEffect(() => {
|
|
155
|
+
// Pre-check on mount
|
|
156
|
+
checkCreditsAvailable(user?.uid, 5).then(setCreditCheck);
|
|
157
|
+
}, [user]);
|
|
158
|
+
|
|
159
|
+
if (!creditCheck) return <ActivityIndicator />;
|
|
160
|
+
|
|
161
|
+
return (
|
|
162
|
+
<View>
|
|
163
|
+
<Text>Required: {creditCheck.required} credits</Text>
|
|
164
|
+
<Text>Balance: {creditCheck.currentBalance} credits</Text>
|
|
165
|
+
|
|
166
|
+
{creditCheck.canProceed ? (
|
|
167
|
+
<Button
|
|
168
|
+
onPress={() => executeAction()}
|
|
169
|
+
title="Proceed"
|
|
170
|
+
/>
|
|
171
|
+
) : (
|
|
172
|
+
<Button
|
|
173
|
+
onPress={() => showPaywall()}
|
|
174
|
+
title="Get More Credits"
|
|
175
|
+
/>
|
|
176
|
+
)}
|
|
177
|
+
</View>
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### With Cost Estimation
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
function CostEstimator() {
|
|
186
|
+
const { user } = useAuth();
|
|
187
|
+
const { checkCreditsAvailable } = useCreditChecker();
|
|
188
|
+
|
|
189
|
+
const estimateCost = (itemCount: number) => {
|
|
190
|
+
return Math.ceil(itemCount / 10); // 1 credit per 10 items
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const handleExport = async (items: any[]) => {
|
|
194
|
+
const cost = estimateCost(items.length);
|
|
195
|
+
const result = await checkCreditsAvailable(user?.uid, cost);
|
|
196
|
+
|
|
197
|
+
if (!result.canProceed) {
|
|
198
|
+
Alert.alert(
|
|
199
|
+
'Insufficient Credits',
|
|
200
|
+
`Exporting ${items.length} items costs ${cost} credits. You have ${result.currentBalance}.`
|
|
201
|
+
);
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
await exportItems(items);
|
|
206
|
+
await deductCreditsAfterSuccess(user?.uid, cost);
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
return (
|
|
210
|
+
<FlatList
|
|
211
|
+
data={items}
|
|
212
|
+
renderItem={({ item }) => <ItemRow item={item} />}
|
|
213
|
+
ListHeaderComponent={
|
|
214
|
+
<Button
|
|
215
|
+
onPress={() => handleExport(selectedItems)}
|
|
216
|
+
title={`Export (${estimateCost(selectedItems.length)} credits)`}
|
|
217
|
+
/>
|
|
218
|
+
}
|
|
219
|
+
/>
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Examples
|
|
225
|
+
|
|
226
|
+
### AI Generation with Credits
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
function AIGeneration() {
|
|
230
|
+
const { user } = useAuth();
|
|
231
|
+
const { checkCreditsAvailable, deductCreditsAfterSuccess } = useCreditChecker({
|
|
232
|
+
onCreditDeducted: (userId, cost) => {
|
|
233
|
+
analytics.track('ai_generation_completed', { userId, cost });
|
|
234
|
+
},
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
const creditsNeeded = 5;
|
|
238
|
+
|
|
239
|
+
const handleGenerate = async () => {
|
|
240
|
+
// Check if user has enough credits
|
|
241
|
+
const check = await checkCreditsAvailable(user?.uid, creditsNeeded);
|
|
242
|
+
|
|
243
|
+
if (!check.canProceed) {
|
|
244
|
+
Alert.alert(
|
|
245
|
+
'Insufficient Credits',
|
|
246
|
+
`You need ${creditsNeeded} credits to generate. Current balance: ${check.currentBalance}`,
|
|
247
|
+
[
|
|
248
|
+
{ text: 'Cancel' },
|
|
249
|
+
{ text: 'Get Credits', onPress: () => navigation.navigate('CreditPackages') },
|
|
250
|
+
]
|
|
251
|
+
);
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
// Show loading
|
|
257
|
+
setGenerating(true);
|
|
258
|
+
|
|
259
|
+
// Generate AI content
|
|
260
|
+
const result = await callAIGenerationAPI(prompt);
|
|
261
|
+
|
|
262
|
+
// Only deduct credits after successful generation
|
|
263
|
+
await deductCreditsAfterSuccess(user?.uid, creditsNeeded);
|
|
264
|
+
|
|
265
|
+
setContent(result);
|
|
266
|
+
} catch (error) {
|
|
267
|
+
Alert.alert('Error', 'Failed to generate content');
|
|
268
|
+
} finally {
|
|
269
|
+
setGenerating(false);
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
return (
|
|
274
|
+
<View>
|
|
275
|
+
<Text>Credits needed: {creditsNeeded}</Text>
|
|
276
|
+
<Button
|
|
277
|
+
onPress={handleGenerate}
|
|
278
|
+
disabled={generating}
|
|
279
|
+
title={generating ? 'Generating...' : `Generate (${creditsNeeded} credits)`}
|
|
280
|
+
/>
|
|
281
|
+
</View>
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Batch Operations
|
|
287
|
+
|
|
288
|
+
```typescript
|
|
289
|
+
function BatchOperations() {
|
|
290
|
+
const { user } = useAuth();
|
|
291
|
+
const { checkCreditsAvailable, deductCreditsAfterSuccess } = useCreditChecker();
|
|
292
|
+
|
|
293
|
+
const handleBatchProcess = async (items: Item[]) => {
|
|
294
|
+
const cost = items.length; // 1 credit per item
|
|
295
|
+
|
|
296
|
+
const check = await checkCreditsAvailable(user?.uid, cost);
|
|
297
|
+
|
|
298
|
+
if (!check.canProceed) {
|
|
299
|
+
Alert.alert(
|
|
300
|
+
'Insufficient Credits',
|
|
301
|
+
`Processing ${items.length} items requires ${cost} credits. You have ${check.currentBalance}.`,
|
|
302
|
+
[
|
|
303
|
+
{ text: 'Cancel' },
|
|
304
|
+
{
|
|
305
|
+
text: 'Get Credits',
|
|
306
|
+
onPress: () => navigation.navigate('CreditPackages', { required: cost }),
|
|
307
|
+
},
|
|
308
|
+
]
|
|
309
|
+
);
|
|
310
|
+
return;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Confirm before proceeding
|
|
314
|
+
Alert.alert(
|
|
315
|
+
'Confirm Batch Process',
|
|
316
|
+
`Process ${items.length} items for ${cost} credits?`,
|
|
317
|
+
[
|
|
318
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
319
|
+
{
|
|
320
|
+
text: 'Process',
|
|
321
|
+
onPress: async () => {
|
|
322
|
+
try {
|
|
323
|
+
// Process all items
|
|
324
|
+
for (const item of items) {
|
|
325
|
+
await processItem(item);
|
|
326
|
+
updateProgress();
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// Deduct only after all succeed
|
|
330
|
+
await deductCreditsAfterSuccess(user?.uid, cost);
|
|
331
|
+
|
|
332
|
+
Alert.alert('Success', `Processed ${items.length} items`);
|
|
333
|
+
} catch (error) {
|
|
334
|
+
Alert.alert('Error', 'Batch processing failed');
|
|
335
|
+
}
|
|
336
|
+
},
|
|
337
|
+
},
|
|
338
|
+
]
|
|
339
|
+
);
|
|
340
|
+
};
|
|
341
|
+
|
|
342
|
+
return (
|
|
343
|
+
<Button
|
|
344
|
+
onPress={() => handleBatchProcess(selectedItems)}
|
|
345
|
+
title={`Process ${selectedItems.length} items`}
|
|
346
|
+
/>
|
|
347
|
+
);
|
|
348
|
+
}
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Progressive Credit Check
|
|
352
|
+
|
|
353
|
+
```typescript
|
|
354
|
+
function ProgressiveFeature() {
|
|
355
|
+
const { user } = useAuth();
|
|
356
|
+
const { checkCreditsAvailable } = useCreditChecker();
|
|
357
|
+
|
|
358
|
+
const handleProgressiveAction = async () => {
|
|
359
|
+
// Try from most expensive to least expensive
|
|
360
|
+
const tiers = [10, 5, 3, 1];
|
|
361
|
+
|
|
362
|
+
for (const cost of tiers) {
|
|
363
|
+
const check = await checkCreditsAvailable(user?.uid, cost);
|
|
364
|
+
|
|
365
|
+
if (check.canProceed) {
|
|
366
|
+
// Use the highest tier user can afford
|
|
367
|
+
await executeAction(cost);
|
|
368
|
+
Alert.alert('Success', `Used ${cost} credits`);
|
|
369
|
+
return;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
// User can't afford any tier
|
|
374
|
+
Alert.alert('Insufficient Credits', 'You need at least 1 credit to proceed');
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
return (
|
|
378
|
+
<Button
|
|
379
|
+
onPress={handleProgressiveAction}
|
|
380
|
+
title="Smart Action (1-10 credits)"
|
|
381
|
+
/>
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
## Best Practices
|
|
387
|
+
|
|
388
|
+
1. **Check before deduct** - Always verify credits before operations
|
|
389
|
+
2. **Deduct after success** - Only deduct when operation succeeds
|
|
390
|
+
3. **Show clear messaging** - Tell users cost and balance
|
|
391
|
+
4. **Handle failures** - Don't deduct on error
|
|
392
|
+
5. **Track deductions** - Use callback for analytics
|
|
393
|
+
6. **Provide alternatives** - Link to credit purchase when low
|
|
394
|
+
7. **Estimate costs** - Calculate and show cost upfront
|
|
395
|
+
|
|
396
|
+
## Related Hooks
|
|
397
|
+
|
|
398
|
+
- **useCredits** - For accessing credits balance
|
|
399
|
+
- **useDeductCredit** - For direct credit deduction
|
|
400
|
+
- **useCreditsGate** - For gating features with credits
|
|
401
|
+
- **useCreditChecker** (utility) - For reusable credit checker
|
|
402
|
+
|
|
403
|
+
## See Also
|
|
404
|
+
|
|
405
|
+
- [Credit Checker Utility](../../../utils/creditChecker.md)
|
|
406
|
+
- [Credits README](../../../domains/wallet/README.md)
|
|
407
|
+
- [Credits Entity](../../../domains/wallet/domain/entities/Credits.md)
|