@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,371 @@
|
|
|
1
|
+
# Paywall Domain
|
|
2
|
+
|
|
3
|
+
Abonelik ve kredi satın alımı için kullanıcı dostu ödeme duvarı (paywall) bileşenleri ve hooks.
|
|
4
|
+
|
|
5
|
+
## Özellikler
|
|
6
|
+
|
|
7
|
+
- **Hazır Paywall Bileşenleri**: Önceden tasarlanmış, özelleştirilebilir paywall UI'ları
|
|
8
|
+
- **Modal ve Full-Screen Desteği**: Modal veya tam ekran paywall seçenekleri
|
|
9
|
+
- **Çoklu Dil Desteği**: Built-in i18n desteği
|
|
10
|
+
- **A/B Test Hazır**: Farklı paywall varyantları kolayca oluşturulabilir
|
|
11
|
+
- **Analytics Entegrasyonu**: Kullanıcı davranışlarını takip edin
|
|
12
|
+
|
|
13
|
+
## Kurulum
|
|
14
|
+
|
|
15
|
+
### Temel Konfigürasyon
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { SubscriptionProvider } from '@umituz/react-native-subscription';
|
|
19
|
+
|
|
20
|
+
function App() {
|
|
21
|
+
return (
|
|
22
|
+
<SubscriptionProvider
|
|
23
|
+
config={{
|
|
24
|
+
revenueCatApiKey: 'your_api_key',
|
|
25
|
+
entitlementId: 'premium',
|
|
26
|
+
}}
|
|
27
|
+
>
|
|
28
|
+
{/* Your app */}
|
|
29
|
+
</SubscriptionProvider>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Kullanım
|
|
35
|
+
|
|
36
|
+
### PaywallModal
|
|
37
|
+
|
|
38
|
+
Modal paywall gösterimi için:
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
import { PaywallModal } from '@umituz/react-native-subscription';
|
|
42
|
+
|
|
43
|
+
function MyComponent() {
|
|
44
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<Button onPress={() => setIsVisible(true)} title="Upgrade to Premium" />
|
|
49
|
+
|
|
50
|
+
<PaywallModal
|
|
51
|
+
isVisible={isVisible}
|
|
52
|
+
onClose={() => setIsVisible(false)}
|
|
53
|
+
config={{
|
|
54
|
+
title: 'Unlock Premium Features',
|
|
55
|
+
description: 'Get unlimited access to all features',
|
|
56
|
+
features: [
|
|
57
|
+
{ icon: 'star', text: 'Unlimited credits' },
|
|
58
|
+
{ icon: 'zap', text: 'AI-powered tools' },
|
|
59
|
+
{ icon: 'shield', text: 'Ad-free experience' },
|
|
60
|
+
],
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
</>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### usePaywall Hook
|
|
69
|
+
|
|
70
|
+
Paywall görünürlüğünü ve davranışlarını kontrol etmek için:
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
import { usePaywall } from '@umituz/react-native-subscription';
|
|
74
|
+
|
|
75
|
+
function PremiumFeature() {
|
|
76
|
+
const { showPaywall, hidePaywall, isPaywallVisible } = usePaywall();
|
|
77
|
+
|
|
78
|
+
const handleUpgradeClick = () => {
|
|
79
|
+
showPaywall({
|
|
80
|
+
trigger: 'premium_button',
|
|
81
|
+
featureId: 'ai_tools',
|
|
82
|
+
});
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<View>
|
|
87
|
+
<Text>Premium Feature</Text>
|
|
88
|
+
<Button onPress={handleUpgradeClick} title="Unlock" />
|
|
89
|
+
</View>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### usePaywallActions Hook
|
|
95
|
+
|
|
96
|
+
Paywall aksiyonları için:
|
|
97
|
+
|
|
98
|
+
```typescript
|
|
99
|
+
import { usePaywallActions } from '@umituz/react-native-subscription';
|
|
100
|
+
|
|
101
|
+
function PaywallHandler() {
|
|
102
|
+
const { handlePurchase, handleRestore, isLoading } = usePaywallActions();
|
|
103
|
+
|
|
104
|
+
return (
|
|
105
|
+
<View>
|
|
106
|
+
<Button
|
|
107
|
+
onPress={handlePurchase}
|
|
108
|
+
disabled={isLoading}
|
|
109
|
+
title="Subscribe Now"
|
|
110
|
+
/>
|
|
111
|
+
<Button onPress={handleRestore} title="Restore Purchase" />
|
|
112
|
+
</View>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### useSubscriptionModal Hook
|
|
118
|
+
|
|
119
|
+
Subscription modal yönetimi için:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { useSubscriptionModal } from '@umituz/react-native-subscription';
|
|
123
|
+
|
|
124
|
+
function SubscriptionButton() {
|
|
125
|
+
const { openModal, closeModal, isModalOpen } = useSubscriptionModal();
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<>
|
|
129
|
+
<Button onPress={openModal} title="View Plans" />
|
|
130
|
+
<SubscriptionModal
|
|
131
|
+
isOpen={isModalOpen}
|
|
132
|
+
onClose={closeModal}
|
|
133
|
+
/>
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Bileşenler
|
|
140
|
+
|
|
141
|
+
### PaywallContainer
|
|
142
|
+
|
|
143
|
+
Paywall içerik wrapper'ı:
|
|
144
|
+
|
|
145
|
+
```typescript
|
|
146
|
+
import { PaywallContainer } from '@umituz/react-native-subscription';
|
|
147
|
+
|
|
148
|
+
<PaywallContainer
|
|
149
|
+
config={{
|
|
150
|
+
theme: 'dark',
|
|
151
|
+
showCloseButton: true,
|
|
152
|
+
closeOnBackdropPress: false,
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
{/* Paywall content */}
|
|
156
|
+
</PaywallContainer>
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### PaywallScreen
|
|
160
|
+
|
|
161
|
+
Tam ekran paywall:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { PaywallScreen } from '@umituz/react-native-subscription';
|
|
165
|
+
|
|
166
|
+
<PaywallScreen
|
|
167
|
+
packages={subscriptionPackages}
|
|
168
|
+
onPackageSelect={handlePackageSelect}
|
|
169
|
+
config={{
|
|
170
|
+
highlightPackage: 'annual',
|
|
171
|
+
showPerks: true,
|
|
172
|
+
showTerms: true,
|
|
173
|
+
}}
|
|
174
|
+
translations={{
|
|
175
|
+
title: 'Choose Your Plan',
|
|
176
|
+
subtitle: 'Cancel anytime',
|
|
177
|
+
terms: 'Terms & Privacy Policy',
|
|
178
|
+
}}
|
|
179
|
+
/>
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Hooks Referansı
|
|
183
|
+
|
|
184
|
+
### usePaywall
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
const {
|
|
188
|
+
showPaywall, // Paywall göster
|
|
189
|
+
hidePaywall, // Paywall gizle
|
|
190
|
+
isPaywallVisible, // Paywall görünürlük durumu
|
|
191
|
+
paywallConfig, // Mevcut konfigürasyon
|
|
192
|
+
} = usePaywall();
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
### usePaywallActions
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
const {
|
|
199
|
+
handlePurchase, // Satın alma işlemi
|
|
200
|
+
handleRestore, // Satın alma geri yükleme
|
|
201
|
+
isLoading, // Yüklenme durumu
|
|
202
|
+
error, // Hata mesajı
|
|
203
|
+
selectedPackage, // Seçili paket
|
|
204
|
+
} = usePaywallActions();
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### usePaywallTranslations
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
const {
|
|
211
|
+
translations, // Çeviri objeleri
|
|
212
|
+
t, // Çeviri fonksiyonu
|
|
213
|
+
isLoading, // Yüklenme durumu
|
|
214
|
+
} = usePaywallTranslations({
|
|
215
|
+
language: 'tr',
|
|
216
|
+
fallbackLanguage: 'en',
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Özelleştirme
|
|
221
|
+
|
|
222
|
+
### Tema Konfigürasyonu
|
|
223
|
+
|
|
224
|
+
```typescript
|
|
225
|
+
const customTheme = {
|
|
226
|
+
colors: {
|
|
227
|
+
primary: '#FF6B6B',
|
|
228
|
+
background: '#1A1A1A',
|
|
229
|
+
text: '#FFFFFF',
|
|
230
|
+
textSecondary: '#A0A0A0',
|
|
231
|
+
},
|
|
232
|
+
fonts: {
|
|
233
|
+
title: { fontSize: 28, fontWeight: 'bold' },
|
|
234
|
+
body: { fontSize: 16, fontWeight: 'normal' },
|
|
235
|
+
},
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
<PaywallModal theme={customTheme} />
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Özel Feature Listesi
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const customFeatures = [
|
|
245
|
+
{
|
|
246
|
+
id: 'feature1',
|
|
247
|
+
icon: 'rocket',
|
|
248
|
+
title: 'AI-Powered Tools',
|
|
249
|
+
description: 'Advanced AI features',
|
|
250
|
+
highlight: true,
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: 'feature2',
|
|
254
|
+
icon: 'infinity',
|
|
255
|
+
title: 'Unlimited Credits',
|
|
256
|
+
description: 'Never run out of credits',
|
|
257
|
+
},
|
|
258
|
+
];
|
|
259
|
+
|
|
260
|
+
<PaywallScreen features={customFeatures} />
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Event Tracking
|
|
264
|
+
|
|
265
|
+
Analytics entegrasyonu için:
|
|
266
|
+
|
|
267
|
+
```typescript
|
|
268
|
+
import { usePaywallFeedback } from '@umituz/react-native-subscription';
|
|
269
|
+
|
|
270
|
+
function PaywallWithTracking() {
|
|
271
|
+
const { trackEvent, trackPurchase, trackDismiss } = usePaywallFeedback();
|
|
272
|
+
|
|
273
|
+
useEffect(() => {
|
|
274
|
+
trackEvent('paywall_impression', {
|
|
275
|
+
source: 'home_screen',
|
|
276
|
+
});
|
|
277
|
+
}, []);
|
|
278
|
+
|
|
279
|
+
const handlePurchase = async () => {
|
|
280
|
+
await purchasePackage();
|
|
281
|
+
trackPurchase('premium_monthly', {
|
|
282
|
+
revenue: 9.99,
|
|
283
|
+
currency: 'USD',
|
|
284
|
+
});
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const handleClose = () => {
|
|
288
|
+
trackDismiss('paywall_closed', {
|
|
289
|
+
duration: 30, // seconds
|
|
290
|
+
});
|
|
291
|
+
closeModal();
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
## Best Practices
|
|
297
|
+
|
|
298
|
+
1. **Trigger Bazlı Gösterim**: Farklı trigger'lar için farklı paywall'lar kullanın
|
|
299
|
+
2. **A/B Test**: Farklı varyasyonları test edin
|
|
300
|
+
3. **Analytics**: Kullanıcı davranışlarını takip edin
|
|
301
|
+
4. **Copywriting**: Farklı dillerde optimize edilmiş copy kullanın
|
|
302
|
+
5. **Loading States**: Satın alma sırasında loading gösterin
|
|
303
|
+
6. **Error Handling**: Hataları kullanıcı dostu mesajlarla gösterin
|
|
304
|
+
|
|
305
|
+
## Örnek Uygulama
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import React, { useState } from 'react';
|
|
309
|
+
import { View, Button } from 'react-native';
|
|
310
|
+
import {
|
|
311
|
+
PaywallModal,
|
|
312
|
+
usePaywall,
|
|
313
|
+
usePaywallActions,
|
|
314
|
+
} from '@umituz/react-native-subscription';
|
|
315
|
+
|
|
316
|
+
export default function PaywallExample() {
|
|
317
|
+
const { isPaywallVisible, showPaywall, hidePaywall } = usePaywall();
|
|
318
|
+
const { handlePurchase, isLoading } = usePaywallActions();
|
|
319
|
+
|
|
320
|
+
return (
|
|
321
|
+
<View>
|
|
322
|
+
<Button
|
|
323
|
+
onPress={() => showPaywall({ trigger: 'upgrade_button' })}
|
|
324
|
+
title="Upgrade to Premium"
|
|
325
|
+
/>
|
|
326
|
+
|
|
327
|
+
<PaywallModal
|
|
328
|
+
isVisible={isPaywallVisible}
|
|
329
|
+
onClose={hidePaywall}
|
|
330
|
+
config={{
|
|
331
|
+
title: 'Go Premium',
|
|
332
|
+
description: 'Unlock all features',
|
|
333
|
+
features: [
|
|
334
|
+
{ icon: 'star', text: 'Unlimited access' },
|
|
335
|
+
{ icon: 'zap', text: 'AI features' },
|
|
336
|
+
{ icon: 'shield', text: 'No ads' },
|
|
337
|
+
],
|
|
338
|
+
}}
|
|
339
|
+
onPurchase={handlePurchase}
|
|
340
|
+
isLoading={isLoading}
|
|
341
|
+
/>
|
|
342
|
+
</View>
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Tip Tanımlamaları
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
interface PaywallConfig {
|
|
351
|
+
title?: string;
|
|
352
|
+
description?: string;
|
|
353
|
+
features?: PaywallFeature[];
|
|
354
|
+
theme?: 'light' | 'dark';
|
|
355
|
+
showCloseButton?: boolean;
|
|
356
|
+
closeOnBackdropPress?: boolean;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
interface PaywallFeature {
|
|
360
|
+
icon: string;
|
|
361
|
+
text: string;
|
|
362
|
+
description?: string;
|
|
363
|
+
highlight?: boolean;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
interface PaywallTrigger {
|
|
367
|
+
trigger: string;
|
|
368
|
+
featureId?: string;
|
|
369
|
+
source?: string;
|
|
370
|
+
}
|
|
371
|
+
```
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Paywall Header
|
|
3
|
-
* Header with
|
|
3
|
+
* Header with background, close button, title and subtitle
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React from "react";
|
|
7
7
|
import { View, StyleSheet, TouchableOpacity } from "react-native";
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
import {
|
|
10
10
|
AtomicText,
|
|
11
11
|
AtomicIcon,
|
|
@@ -25,16 +25,13 @@ export const PaywallHeader: React.FC<PaywallHeaderProps> = React.memo(
|
|
|
25
25
|
const { themeMode } = useDesignSystemTheme();
|
|
26
26
|
const isDark = themeMode === "dark";
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
?
|
|
30
|
-
:
|
|
28
|
+
const backgroundColor = isDark
|
|
29
|
+
? tokens.colors.surface
|
|
30
|
+
: tokens.colors.primary;
|
|
31
31
|
|
|
32
32
|
return (
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
start={{ x: 0, y: 0 }}
|
|
36
|
-
end={{ x: 1, y: 1 }}
|
|
37
|
-
style={styles.container}
|
|
33
|
+
<View
|
|
34
|
+
style={[styles.container, { backgroundColor }]}
|
|
38
35
|
>
|
|
39
36
|
<TouchableOpacity
|
|
40
37
|
onPress={onClose}
|
|
@@ -66,7 +63,7 @@ export const PaywallHeader: React.FC<PaywallHeaderProps> = React.memo(
|
|
|
66
63
|
</View>
|
|
67
64
|
|
|
68
65
|
<View style={[styles.wave, { backgroundColor: tokens.colors.background }]} />
|
|
69
|
-
</
|
|
66
|
+
</View>
|
|
70
67
|
);
|
|
71
68
|
}
|
|
72
69
|
);
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Paywall Components
|
|
2
|
+
|
|
3
|
+
UI components for displaying paywalls and upgrade prompts.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
This directory contains React Native components for rendering paywall screens and upgrade prompts.
|
|
8
|
+
|
|
9
|
+
## Components
|
|
10
|
+
|
|
11
|
+
### PaywallScreen
|
|
12
|
+
Main paywall screen with package selection.
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
function PaywallScreen() {
|
|
16
|
+
const { packages, isLoading } = useSubscriptionPackages();
|
|
17
|
+
const { handlePurchase, handleRestore } = usePaywallOperations({
|
|
18
|
+
userId: user?.uid,
|
|
19
|
+
isAnonymous: !user,
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
if (isLoading) return <LoadingScreen />;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ScrollView>
|
|
26
|
+
<PaywallHeader />
|
|
27
|
+
|
|
28
|
+
{packages.map((pkg) => (
|
|
29
|
+
<PackageCard
|
|
30
|
+
key={pkg.identifier}
|
|
31
|
+
package={pkg}
|
|
32
|
+
onPress={() => handlePurchase(pkg)}
|
|
33
|
+
/>
|
|
34
|
+
))}
|
|
35
|
+
|
|
36
|
+
<RestoreButton onPress={handleRestore} />
|
|
37
|
+
</ScrollView>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### PackageCard
|
|
43
|
+
Individual subscription package display card.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
interface PackageCardProps {
|
|
47
|
+
package: PaywallPackage;
|
|
48
|
+
selected?: boolean;
|
|
49
|
+
onPress: () => void;
|
|
50
|
+
popular?: boolean;
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Features:**
|
|
55
|
+
- Highlight popular packages
|
|
56
|
+
- Show price and period
|
|
57
|
+
- Display features list
|
|
58
|
+
- Show savings (for annual)
|
|
59
|
+
- Visual selection indicator
|
|
60
|
+
|
|
61
|
+
### PaywallModal
|
|
62
|
+
Modal-style paywall overlay.
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
interface PaywallModalProps {
|
|
66
|
+
visible: boolean;
|
|
67
|
+
onClose: () => void;
|
|
68
|
+
onPurchase: (pkg: Package) => void;
|
|
69
|
+
configuration: PaywallConfig;
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Usage:**
|
|
74
|
+
```typescript
|
|
75
|
+
<PaywallModal
|
|
76
|
+
visible={showPaywall}
|
|
77
|
+
onClose={() => setShowPaywall(false)}
|
|
78
|
+
onPurchase={handlePurchase}
|
|
79
|
+
configuration={{
|
|
80
|
+
title: 'Upgrade to Premium',
|
|
81
|
+
features: ['Unlimited access', 'Ad-free'],
|
|
82
|
+
packages: packages,
|
|
83
|
+
}}
|
|
84
|
+
/>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### PremiumFeatureLock
|
|
88
|
+
Locked feature indicator that prompts upgrade.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
interface PremiumFeatureLockProps {
|
|
92
|
+
feature: string;
|
|
93
|
+
onPress: () => void;
|
|
94
|
+
icon?: string;
|
|
95
|
+
message?: string;
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Usage:**
|
|
100
|
+
```typescript
|
|
101
|
+
<PremiumFeatureLock
|
|
102
|
+
feature="AI Generation"
|
|
103
|
+
onPress={() => showPaywall({ type: 'premium_feature', feature: 'ai_generation' })}
|
|
104
|
+
message="Upgrade to generate unlimited content"
|
|
105
|
+
icon="lock"
|
|
106
|
+
/>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Usage Patterns
|
|
110
|
+
|
|
111
|
+
### With Navigation
|
|
112
|
+
```typescript
|
|
113
|
+
function navigateToPaywall(trigger: PaywallTrigger) {
|
|
114
|
+
navigation.navigate('Paywall', { trigger });
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// In paywall screen
|
|
118
|
+
const { trigger } = route.params;
|
|
119
|
+
const config = getPaywallConfig(trigger.type);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### With Inline Paywall
|
|
123
|
+
```typescript
|
|
124
|
+
function InlinePaywall({ onUpgrade, onDismiss }) {
|
|
125
|
+
return (
|
|
126
|
+
<Card>
|
|
127
|
+
<Image source={premiumIllustration} />
|
|
128
|
+
<Title>Unlock Premium Features</Title>
|
|
129
|
+
<FeaturesList features={premiumFeatures} />
|
|
130
|
+
<Button onPress={onUpgrade}>Upgrade Now</Button>
|
|
131
|
+
<Link onPress={onDismiss}>Maybe Later</Link>
|
|
132
|
+
</Card>
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### With Context
|
|
138
|
+
```typescript
|
|
139
|
+
function ContextualPaywall({ feature, context }) {
|
|
140
|
+
const { packages } = useSubscriptionPackages();
|
|
141
|
+
|
|
142
|
+
return (
|
|
143
|
+
<PaywallScreen
|
|
144
|
+
title={`Unlock ${feature}`}
|
|
145
|
+
subtitle={`You need Premium to use ${feature}`}
|
|
146
|
+
highlightPackage={context.recommendedPackage}
|
|
147
|
+
packages={packages}
|
|
148
|
+
/>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Styling
|
|
154
|
+
|
|
155
|
+
Components use design tokens for consistent styling:
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { useAppDesignTokens } from '@umituz/react-native-design-system';
|
|
159
|
+
|
|
160
|
+
const tokens = useAppDesignTokens();
|
|
161
|
+
|
|
162
|
+
const styles = StyleSheet.create({
|
|
163
|
+
card: {
|
|
164
|
+
backgroundColor: tokens.colors.surface,
|
|
165
|
+
borderRadius: tokens.radius.lg,
|
|
166
|
+
padding: tokens.spacing.lg,
|
|
167
|
+
},
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Best Practices
|
|
172
|
+
|
|
173
|
+
1. **Clear Value**: Communicate premium benefits clearly
|
|
174
|
+
2. **Visual Hierarchy**: Highlight recommended package
|
|
175
|
+
3. **Social Proof**: Show user counts or testimonials
|
|
176
|
+
4. **Easy Dismissal**: Allow users to close when appropriate
|
|
177
|
+
5. **Smooth Purchase**: Make purchase flow simple
|
|
178
|
+
6. **Loading States**: Show appropriate loading indicators
|
|
179
|
+
7. **Error Handling**: Handle purchase failures gracefully
|
|
180
|
+
|
|
181
|
+
## Related
|
|
182
|
+
|
|
183
|
+
- [Paywall README](../README.md)
|
|
184
|
+
- [PaywallVisibility Hook](../../hooks/usePaywallVisibility.md)
|
|
185
|
+
- [Premium Components](../../components/details/README.md)
|