@umituz/react-native-subscription 2.37.98 → 2.37.100
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.37.
|
|
3
|
+
"version": "2.37.100",
|
|
4
4
|
"description": "Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -3,7 +3,8 @@ import { StyleSheet } from "react-native";
|
|
|
3
3
|
|
|
4
4
|
export const paywallModalStyles = StyleSheet.create({
|
|
5
5
|
modalContent: { padding: 0, borderWidth: 0, overflow: "hidden" },
|
|
6
|
-
container: { flex: 1 },
|
|
6
|
+
container: { flex: 1, flexDirection: "column" as const },
|
|
7
|
+
scrollContainer: { flex: 1, flexShrink: 1 },
|
|
7
8
|
closeBtn: {
|
|
8
9
|
position: "absolute",
|
|
9
10
|
top: 12,
|
|
@@ -35,7 +36,7 @@ export const paywallModalStyles = StyleSheet.create({
|
|
|
35
36
|
loading: { alignItems: "center", paddingVertical: 24 },
|
|
36
37
|
loadingText: { marginTop: 8 },
|
|
37
38
|
plans: { marginBottom: 12 },
|
|
38
|
-
stickyFooter: { paddingHorizontal: 16, paddingTop: 12, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: "rgba(128,128,128,0.2)" },
|
|
39
|
+
stickyFooter: { flexShrink: 0, paddingHorizontal: 16, paddingTop: 12, borderTopWidth: StyleSheet.hairlineWidth, borderTopColor: "rgba(128,128,128,0.2)" },
|
|
39
40
|
cta: { borderRadius: 12, paddingVertical: 14, alignItems: "center", marginBottom: 12 },
|
|
40
41
|
ctaDisabled: { opacity: 0.5 },
|
|
41
42
|
ctaText: { fontWeight: "700" },
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import React, { useCallback, useEffect } from "react";
|
|
2
|
-
import { View, TouchableOpacity, Linking } from "react-native";
|
|
2
|
+
import { View, ScrollView, TouchableOpacity, Linking } from "react-native";
|
|
3
3
|
import { AtomicText, AtomicIcon, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
|
|
4
4
|
import { BaseModal } from "@umituz/react-native-design-system/molecules";
|
|
5
5
|
import { useSafeAreaInsets } from "@umituz/react-native-design-system/safe-area";
|
|
6
6
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
7
|
-
import { ScreenLayout } from "../../../shared/presentation";
|
|
8
7
|
import { Image } from "expo-image";
|
|
9
8
|
import { PlanCard } from "./PlanCard";
|
|
10
9
|
import { paywallModalStyles as styles } from "./PaywallModal.styles";
|
|
@@ -57,7 +56,7 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
57
56
|
</TouchableOpacity>
|
|
58
57
|
|
|
59
58
|
{/* Scrollable content — plan cards scroll, CTA is always pinned below */}
|
|
60
|
-
<
|
|
59
|
+
<ScrollView style={styles.scrollContainer} contentContainerStyle={styles.scroll} showsVerticalScrollIndicator={false}>
|
|
61
60
|
{heroImage && <View style={styles.heroContainer}><Image source={heroImage} style={styles.heroImage} contentFit="cover" transition={0} /></View>}
|
|
62
61
|
<View style={styles.header}>
|
|
63
62
|
<AtomicText type="headlineMedium" adjustsFontSizeToFit numberOfLines={2} minimumFontScale={0.75} style={[styles.title, { color: tokens.colors.textPrimary }]}>{translations.title}</AtomicText>
|
|
@@ -85,7 +84,7 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
85
84
|
})
|
|
86
85
|
)}
|
|
87
86
|
</View>
|
|
88
|
-
</
|
|
87
|
+
</ScrollView>
|
|
89
88
|
|
|
90
89
|
{/* Sticky footer — always visible, never hidden behind scroll content */}
|
|
91
90
|
<View style={[styles.stickyFooter, { paddingBottom: Math.max(insets.bottom, 16) }]}>
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2024 Ümit UZ
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
package/README.md
DELETED
|
@@ -1,323 +0,0 @@
|
|
|
1
|
-
# @umituz/react-native-subscription
|
|
2
|
-
|
|
3
|
-
Complete subscription management with RevenueCat, paywall UI, and credits system for React Native apps.
|
|
4
|
-
|
|
5
|
-
## Package Overview
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**Version**: Latest
|
|
10
|
-
|
|
11
|
-
**Type**: React Native Package
|
|
12
|
-
|
|
13
|
-
This package provides comprehensive subscription and credit management with:
|
|
14
|
-
- RevenueCat integration for subscriptions
|
|
15
|
-
- Credits system with transaction tracking
|
|
16
|
-
- Paywall UI components
|
|
17
|
-
- Feature gating (premium, auth, credits)
|
|
18
|
-
- DDD architecture with clean layers
|
|
19
|
-
|
|
20
|
-
## Strategy
|
|
21
|
-
|
|
22
|
-
### Architecture Principles
|
|
23
|
-
|
|
24
|
-
1. **Domain-Driven Design (DDD)**
|
|
25
|
-
- Separate domains: Wallet, Paywall, Config
|
|
26
|
-
- Each domain has its own entities, rules, and boundaries
|
|
27
|
-
- Business logic stays in domain layer
|
|
28
|
-
|
|
29
|
-
2. **Clean Architecture**
|
|
30
|
-
- Presentation: React hooks and components
|
|
31
|
-
- Application: Use cases and orchestration
|
|
32
|
-
- Domain: Entities and business rules
|
|
33
|
-
- Infrastructure: External integrations
|
|
34
|
-
|
|
35
|
-
3. **Separation of Concerns**
|
|
36
|
-
- UI components are pure and reusable
|
|
37
|
-
- Business logic is in hooks and services
|
|
38
|
-
- Data persistence is abstracted behind repositories
|
|
39
|
-
|
|
40
|
-
### Integration Flow
|
|
41
|
-
|
|
42
|
-
1. **Initialization**
|
|
43
|
-
- Configure RevenueCat with API key
|
|
44
|
-
- Set up Firebase for credits storage
|
|
45
|
-
- Initialize providers at app root
|
|
46
|
-
|
|
47
|
-
2. **Subscription Management**
|
|
48
|
-
- Check user tier and subscription status
|
|
49
|
-
- Gate premium features
|
|
50
|
-
- Handle purchase flows
|
|
51
|
-
|
|
52
|
-
3. **Credits System**
|
|
53
|
-
- Initialize credits on purchase
|
|
54
|
-
- Deduct credits for feature usage
|
|
55
|
-
- Track all transactions
|
|
56
|
-
- Handle credit exhaustion
|
|
57
|
-
|
|
58
|
-
4. **Paywall Display**
|
|
59
|
-
- Show paywall on feature gates
|
|
60
|
-
- Handle purchase operations
|
|
61
|
-
- Manage paywall visibility state
|
|
62
|
-
|
|
63
|
-
### Key Dependencies
|
|
64
|
-
|
|
65
|
-
- **RevenueCat**: `react-native-purchases` >= 7.0.0
|
|
66
|
-
- **Firebase**: `firebase` >= 10.0.0
|
|
67
|
-
- **State Management**: `@tanstack/react-query` >= 5.0.0
|
|
68
|
-
- **React Native**: `react-native` >= 0.74.0
|
|
69
|
-
|
|
70
|
-
## RevenueCat Best Practices
|
|
71
|
-
|
|
72
|
-
This package follows RevenueCat's official best practices:
|
|
73
|
-
|
|
74
|
-
### 1. Trust RevenueCat Data
|
|
75
|
-
|
|
76
|
-
- **Expiration dates**: Use RevenueCat's `expirationDate` directly without modification
|
|
77
|
-
- **Premium status**: Check `customerInfo.entitlements.active['premium']`
|
|
78
|
-
- **Server-side validation**: RevenueCat handles receipt validation server-side
|
|
79
|
-
|
|
80
|
-
### 2. CustomerInfo Listener
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
// Real-time subscription updates via listener
|
|
84
|
-
Purchases.addCustomerInfoUpdateListener((info) => {
|
|
85
|
-
const isPremium = !!info.entitlements.active['premium'];
|
|
86
|
-
const expirationDate = info.entitlements.active['premium']?.expirationDate;
|
|
87
|
-
});
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### 3. Entitlements-Based Access
|
|
91
|
-
|
|
92
|
-
- Use entitlements (not product IDs) to gate features
|
|
93
|
-
- Entitlements abstract away platform differences (iOS/Android)
|
|
94
|
-
- Single source of truth for premium access
|
|
95
|
-
|
|
96
|
-
### 4. Testing Guidelines
|
|
97
|
-
|
|
98
|
-
- **Real devices only**: Simulators don't support in-app purchases
|
|
99
|
-
- **TestFlight uses Sandbox**: Short expiration times (5 min for monthly)
|
|
100
|
-
- **App Store Connect delays**: Changes can take hours to propagate
|
|
101
|
-
|
|
102
|
-
### 5. Anonymous to Identified User Transfer
|
|
103
|
-
|
|
104
|
-
When user converts from anonymous to identified:
|
|
105
|
-
- `Purchases.logIn(userId)` handles user identity
|
|
106
|
-
- Configure "Transfer if no purchases" in RevenueCat dashboard
|
|
107
|
-
- Use `restorePurchases()` for explicit restore
|
|
108
|
-
|
|
109
|
-
### Sources
|
|
110
|
-
|
|
111
|
-
- [RevenueCat React Native SDK](https://github.com/RevenueCat/react-native-purchases)
|
|
112
|
-
- [RevenueCat Documentation](https://www.revenuecat.com/docs/getting-started/installation/reactnative)
|
|
113
|
-
- [Best Practices Guide](https://www.revenuecat.com/blog/engineering/ad-free-subscriptions-in-react-native/)
|
|
114
|
-
|
|
115
|
-
## Restrictions
|
|
116
|
-
|
|
117
|
-
### REQUIRED
|
|
118
|
-
|
|
119
|
-
- **RevenueCat Configuration**: MUST provide valid API key and entitlement ID
|
|
120
|
-
- **Firebase Setup**: MUST initialize Firebase for credits system
|
|
121
|
-
- **Provider Setup**: MUST wrap app with `SubscriptionProvider`
|
|
122
|
-
- **Authentication**: MUST have authenticated user for credits operations
|
|
123
|
-
- **Error Handling**: MUST handle all error states appropriately
|
|
124
|
-
|
|
125
|
-
### PROHIBITED
|
|
126
|
-
|
|
127
|
-
- **NEVER** use subscription hooks outside provider
|
|
128
|
-
- **NEVER** deduce credits without checking balance first
|
|
129
|
-
- **NEVER** gate features without proper user feedback
|
|
130
|
-
- **DO NOT** bypass gate hooks for premium features
|
|
131
|
-
- **DO NOT** initialize RevenueCat multiple times
|
|
132
|
-
|
|
133
|
-
### CRITICAL SAFETY
|
|
134
|
-
|
|
135
|
-
- **ALWAYS** check loading states before rendering
|
|
136
|
-
- **ALWAYS** handle edge cases (no subscription, expired, etc)
|
|
137
|
-
- **ALWAYS** validate return values from credit operations
|
|
138
|
-
- **NEVER** assume user has premium or credits
|
|
139
|
-
- **MUST** implement proper error boundaries
|
|
140
|
-
|
|
141
|
-
## Rules
|
|
142
|
-
|
|
143
|
-
### Provider Setup
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
// CORRECT - Wrap app with provider
|
|
147
|
-
<SubscriptionProvider config={{ revenueCatApiKey: 'xxx' }}>
|
|
148
|
-
<App />
|
|
149
|
-
</SubscriptionProvider>
|
|
150
|
-
|
|
151
|
-
// INCORRECT - No provider
|
|
152
|
-
<App /> // Hooks will fail
|
|
153
|
-
|
|
154
|
-
// INCORRECT - Multiple providers
|
|
155
|
-
<SubscriptionProvider>
|
|
156
|
-
<SubscriptionProvider> // Duplicate
|
|
157
|
-
<App />
|
|
158
|
-
</SubscriptionProvider>
|
|
159
|
-
</SubscriptionProvider>
|
|
160
|
-
```
|
|
161
|
-
|
|
162
|
-
### Feature Gating
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
// CORRECT - Use gate hooks
|
|
166
|
-
const { canAccess, showPaywall } = usePremiumGate();
|
|
167
|
-
if (!canAccess) {
|
|
168
|
-
showPaywall();
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// INCORRECT - Manual check
|
|
173
|
-
if (!user.isPremium) { // No feedback, no paywall
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
### Credit Operations
|
|
179
|
-
|
|
180
|
-
```typescript
|
|
181
|
-
// CORRECT - Check return value
|
|
182
|
-
const success = await deductCredit(5);
|
|
183
|
-
if (success) {
|
|
184
|
-
executeFeature();
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// INCORRECT - Assume success
|
|
188
|
-
await deductCredit(5);
|
|
189
|
-
executeFeature(); // May execute if deduction failed
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
### Loading States
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
// CORRECT - Respect loading
|
|
196
|
-
if (isLoading) return <Spinner />;
|
|
197
|
-
if (!isPremium) return <UpgradePrompt />;
|
|
198
|
-
return <Content />;
|
|
199
|
-
|
|
200
|
-
// INCORRECT - Ignore loading
|
|
201
|
-
{!isPremium && <UpgradePrompt />} // Flickers during load
|
|
202
|
-
```
|
|
203
|
-
|
|
204
|
-
## AI Agent Guidelines
|
|
205
|
-
|
|
206
|
-
### When Implementing Features
|
|
207
|
-
|
|
208
|
-
1. **Always** use appropriate gate hooks for feature access
|
|
209
|
-
2. **Always** handle loading, error, and empty states
|
|
210
|
-
3. **Always** provide user feedback for blocked features
|
|
211
|
-
4. **Always** check return values from operations
|
|
212
|
-
5. **Never** bypass gate system or checks
|
|
213
|
-
6. **Must** test with different user tiers
|
|
214
|
-
7. **Must** handle network errors gracefully
|
|
215
|
-
|
|
216
|
-
### Implementation Checklist
|
|
217
|
-
|
|
218
|
-
- [ ] Import from correct path
|
|
219
|
-
- [ ] Wrap with necessary providers
|
|
220
|
-
- [ ] Use gate hooks for features
|
|
221
|
-
- [ ] Handle loading states
|
|
222
|
-
- [ ] Handle error states
|
|
223
|
-
- [ ] Provide user feedback
|
|
224
|
-
- [ ] Test with guest user
|
|
225
|
-
- [ ] Test with free user
|
|
226
|
-
- [ ] Test with premium user
|
|
227
|
-
- [ ] Test with no credits
|
|
228
|
-
- [ ] Test with insufficient credits
|
|
229
|
-
|
|
230
|
-
### Common Patterns
|
|
231
|
-
|
|
232
|
-
1. **Premium Feature**: Use `usePremiumGate`
|
|
233
|
-
2. **Credit Feature**: Use `useCreditsGate` or `useDeductCredit`
|
|
234
|
-
3. **Auth Feature**: Use `useAuthGate`
|
|
235
|
-
4. **Combined Gates**: Use `useFeatureGate` for complex scenarios
|
|
236
|
-
5. **Paywall Trigger**: Use `usePaywallVisibility` for global state
|
|
237
|
-
|
|
238
|
-
### Error Scenarios to Handle
|
|
239
|
-
|
|
240
|
-
- **No Subscription**: Show upgrade prompt
|
|
241
|
-
- **Expired Subscription**: Show renewal prompt
|
|
242
|
-
- **No Credits**: Show credit purchase prompt
|
|
243
|
-
- **Insufficient Credits**: Show credit cost and purchase option
|
|
244
|
-
- **Network Error**: Show retry option
|
|
245
|
-
- **Purchase Failed**: Show error message and retry
|
|
246
|
-
|
|
247
|
-
## Documentation Structure
|
|
248
|
-
|
|
249
|
-
### Domain Documentation
|
|
250
|
-
|
|
251
|
-
- **[Wallet Domain](./src/domains/wallet/README.md)**: Credits and transactions
|
|
252
|
-
- **[Paywall Domain](./src/domains/paywall/README.md)**: Paywall components
|
|
253
|
-
- **[Config Domain](./src/domains/config/README.md)**: Configuration management
|
|
254
|
-
|
|
255
|
-
### Layer Documentation
|
|
256
|
-
|
|
257
|
-
- **[Presentation Layer](./src/presentation/README.md)**: Hooks and components
|
|
258
|
-
- **[Application Layer](./src/application/README.md)**: Use cases and ports
|
|
259
|
-
- **[Domain Layer](./src/domain/README.md)**: Entities and logic
|
|
260
|
-
- **[Infrastructure Layer](./src/infrastructure/README.md)**: Repositories and services
|
|
261
|
-
|
|
262
|
-
### Feature Documentation
|
|
263
|
-
|
|
264
|
-
- **[RevenueCat Integration](./src/revenuecat/README.md)**: RevenueCat setup
|
|
265
|
-
- **[Subscription Hooks](./src/presentation/hooks/README.md)**: Available hooks
|
|
266
|
-
- **[Premium Components](./src/presentation/components/README.md)**: UI components
|
|
267
|
-
|
|
268
|
-
### Quick Reference
|
|
269
|
-
|
|
270
|
-
#### Subscription Hooks
|
|
271
|
-
|
|
272
|
-
Location: `src/presentation/hooks/`
|
|
273
|
-
|
|
274
|
-
- `useSubscription` - Core subscription management
|
|
275
|
-
- `usePremium` - Check premium status
|
|
276
|
-
- `usePremiumGate` - Gate premium features
|
|
277
|
-
- `useUserTier` - Get user tier (guest/free/premium)
|
|
278
|
-
|
|
279
|
-
#### Credit Hooks
|
|
280
|
-
|
|
281
|
-
Location: `src/presentation/hooks/`
|
|
282
|
-
|
|
283
|
-
- `useCredits` - Access credit balance
|
|
284
|
-
- `useDeductCredit` - Deduct credits with optimistic updates
|
|
285
|
-
- `useCreditChecker` - Check credit availability
|
|
286
|
-
- `useCreditsGate` - Gate features by credits
|
|
287
|
-
|
|
288
|
-
#### Paywall Hooks
|
|
289
|
-
|
|
290
|
-
Location: `src/presentation/hooks/`
|
|
291
|
-
|
|
292
|
-
- `usePaywallVisibility` - Manage paywall state
|
|
293
|
-
- `usePaywallOperations` - Handle purchase operations
|
|
294
|
-
|
|
295
|
-
#### Components
|
|
296
|
-
|
|
297
|
-
Location: `src/presentation/components/`
|
|
298
|
-
|
|
299
|
-
- `PremiumDetailsCard` - Display subscription details
|
|
300
|
-
- `PremiumStatusBadge` - Show subscription badge
|
|
301
|
-
- `PaywallModal` - Full paywall modal
|
|
302
|
-
- `CreditRow` - Display credit balance with progress
|
|
303
|
-
|
|
304
|
-
## Contributing
|
|
305
|
-
|
|
306
|
-
When contributing to this package:
|
|
307
|
-
|
|
308
|
-
1. **Follow Documentation Template**: Use `README_TEMPLATE.md`
|
|
309
|
-
2. **Update Strategy Section**: Document architectural decisions
|
|
310
|
-
3. **List Restrictions**: Clearly state what's required/prohibited
|
|
311
|
-
4. **Provide Rules**: Show correct/incorrect usage
|
|
312
|
-
5. **AI Guidelines**: Include agent instructions
|
|
313
|
-
6. **No Code Examples**: Keep documentation code-agnostic
|
|
314
|
-
7. **English Only**: All documentation in English
|
|
315
|
-
|
|
316
|
-
## Support
|
|
317
|
-
|
|
318
|
-
- **Issues**: [GitHub Issues](https://github.com/umituz/react-native-subscription/issues)
|
|
319
|
-
- **Author**: Ümit UZ <umit@umituz.com>
|
|
320
|
-
|
|
321
|
-
## License
|
|
322
|
-
|
|
323
|
-
MIT License - see LICENSE file for details
|