@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,314 @@
|
|
|
1
|
+
# PaywallFeedbackModal Component
|
|
2
|
+
|
|
3
|
+
Modal for collecting user feedback when declining paywall/subscription.
|
|
4
|
+
|
|
5
|
+
## Import
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
import { PaywallFeedbackModal } from '@umituz/react-native-subscription';
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Signature
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
interface PaywallFeedbackModalProps {
|
|
15
|
+
visible: boolean;
|
|
16
|
+
onClose: () => void;
|
|
17
|
+
onSubmit: (reason: string) => void;
|
|
18
|
+
title?: string;
|
|
19
|
+
subtitle?: string;
|
|
20
|
+
submitText?: string;
|
|
21
|
+
otherPlaceholder?: string;
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Props
|
|
26
|
+
|
|
27
|
+
| Prop | Type | Default | Description |
|
|
28
|
+
|------|------|---------|-------------|
|
|
29
|
+
| `visible` | `boolean` | **Required** | Modal visibility |
|
|
30
|
+
| `onClose` | `() => void` | **Required** | Close handler |
|
|
31
|
+
| `onSubmit` | `(reason: string) => void` | **Required** | Submit feedback handler |
|
|
32
|
+
| `title` | `string` | `t('paywall.feedback.title')` | Modal title |
|
|
33
|
+
| `subtitle` | `string` | `t('paywall.feedback.subtitle')` | Modal subtitle |
|
|
34
|
+
| `submitText` | `string` | `t('paywall.feedback.submit')` | Submit button text |
|
|
35
|
+
| `otherPlaceholder` | `string` | `t('paywall.feedback.otherPlaceholder')` | Other text input placeholder |
|
|
36
|
+
|
|
37
|
+
## Basic Usage
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
function PaywallScreen() {
|
|
41
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
42
|
+
|
|
43
|
+
const handleClose = () => {
|
|
44
|
+
setShowFeedback(true);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
const handleSubmitFeedback = (reason: string) => {
|
|
48
|
+
analytics.track('paywall_feedback', { reason });
|
|
49
|
+
setShowFeedback(false);
|
|
50
|
+
navigation.goBack();
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<View>
|
|
55
|
+
<PaywallContent onClose={handleClose} />
|
|
56
|
+
|
|
57
|
+
<PaywallFeedbackModal
|
|
58
|
+
visible={showFeedback}
|
|
59
|
+
onClose={() => setShowFeedback(false)}
|
|
60
|
+
onSubmit={handleSubmitFeedback}
|
|
61
|
+
/>
|
|
62
|
+
</View>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Advanced Usage
|
|
68
|
+
|
|
69
|
+
### With Custom Content
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
function CustomFeedbackModal() {
|
|
73
|
+
const [visible, setVisible] = useState(false);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<PaywallFeedbackModal
|
|
77
|
+
visible={visible}
|
|
78
|
+
onClose={() => setVisible(false)}
|
|
79
|
+
onSubmit={(reason) => {
|
|
80
|
+
console.log('Feedback:', reason);
|
|
81
|
+
setVisible(false);
|
|
82
|
+
}}
|
|
83
|
+
title="Help Us Improve"
|
|
84
|
+
subtitle="Why are you not upgrading today?"
|
|
85
|
+
submitText="Send Feedback"
|
|
86
|
+
otherPlaceholder="Please tell us more..."
|
|
87
|
+
/>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### With Analytics Tracking
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
function TrackedFeedbackModal() {
|
|
96
|
+
const [visible, setVisible] = useState(false);
|
|
97
|
+
const [paywallTrigger] = useState('premium_feature');
|
|
98
|
+
|
|
99
|
+
const handleSubmit = (reason: string) => {
|
|
100
|
+
analytics.track('paywall_decline_feedback', {
|
|
101
|
+
reason,
|
|
102
|
+
trigger: paywallTrigger,
|
|
103
|
+
timestamp: Date.now(),
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Send to backend
|
|
107
|
+
api.trackFeedback({
|
|
108
|
+
type: 'paywall_decline',
|
|
109
|
+
reason,
|
|
110
|
+
context: { trigger: paywallTrigger },
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
setVisible(false);
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
return (
|
|
117
|
+
<PaywallFeedbackModal
|
|
118
|
+
visible={visible}
|
|
119
|
+
onClose={() => setVisible(false)}
|
|
120
|
+
onSubmit={handleSubmit}
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### With Conditional Display
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
function ConditionalFeedback() {
|
|
130
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
131
|
+
const [hasSeenFeedback, setHasSeenFeedback] = useState(false);
|
|
132
|
+
|
|
133
|
+
const handleClose = () => {
|
|
134
|
+
// Only show feedback if user hasn't seen it recently
|
|
135
|
+
const lastSeen = await AsyncStorage.getItem('last_feedback_date');
|
|
136
|
+
const daysSinceLastSeen = lastSeen
|
|
137
|
+
? (Date.now() - parseInt(lastSeen)) / (1000 * 60 * 60 * 24)
|
|
138
|
+
: Infinity;
|
|
139
|
+
|
|
140
|
+
if (daysSinceLastSeen > 30) {
|
|
141
|
+
setShowFeedback(true);
|
|
142
|
+
} else {
|
|
143
|
+
navigation.goBack();
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const handleSubmit = async (reason: string) => {
|
|
148
|
+
await AsyncStorage.setItem('last_feedback_date', Date.now().toString());
|
|
149
|
+
setShowFeedback(false);
|
|
150
|
+
navigation.goBack();
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
return (
|
|
154
|
+
<PaywallFeedbackModal
|
|
155
|
+
visible={showFeedback}
|
|
156
|
+
onClose={() => setShowFeedback(false)}
|
|
157
|
+
onSubmit={handleSubmit}
|
|
158
|
+
/>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
## Feedback Options
|
|
164
|
+
|
|
165
|
+
The modal includes these predefined options:
|
|
166
|
+
|
|
167
|
+
1. **too_expensive** - "Too expensive"
|
|
168
|
+
2. **no_need** - "Don't need it right now"
|
|
169
|
+
3. **trying_out** - "Just trying out the app"
|
|
170
|
+
4. **technical_issues** - "Technical issues"
|
|
171
|
+
5. **other** - "Other" (with text input)
|
|
172
|
+
|
|
173
|
+
## Examples
|
|
174
|
+
|
|
175
|
+
### Complete Paywall with Feedback
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
function CompletePaywallFlow() {
|
|
179
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
180
|
+
|
|
181
|
+
const handlePaywallClose = () => {
|
|
182
|
+
setShowFeedback(true);
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
const handleFeedbackSubmit = (reason: string) => {
|
|
186
|
+
// Track feedback
|
|
187
|
+
analytics.track('paywall_feedback_submitted', { reason });
|
|
188
|
+
|
|
189
|
+
// Send to backend
|
|
190
|
+
fetch('/api/feedback', {
|
|
191
|
+
method: 'POST',
|
|
192
|
+
body: JSON.stringify({
|
|
193
|
+
type: 'paywall_decline',
|
|
194
|
+
reason,
|
|
195
|
+
userId: user?.uid,
|
|
196
|
+
timestamp: Date.now(),
|
|
197
|
+
}),
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
setShowFeedback(false);
|
|
201
|
+
navigation.goBack();
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const handleFeedbackSkip = () => {
|
|
205
|
+
analytics.track('paywall_feedback_skipped');
|
|
206
|
+
setShowFeedback(false);
|
|
207
|
+
navigation.goBack();
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<View>
|
|
212
|
+
<PaywallScreen onClose={handlePaywallClose} />
|
|
213
|
+
|
|
214
|
+
<PaywallFeedbackModal
|
|
215
|
+
visible={showFeedback}
|
|
216
|
+
onClose={handleFeedbackSkip}
|
|
217
|
+
onSubmit={handleFeedbackSubmit}
|
|
218
|
+
title="Help Us Improve"
|
|
219
|
+
subtitle="Why are you not upgrading today?"
|
|
220
|
+
submitText="Send Feedback"
|
|
221
|
+
otherPlaceholder="Tell us more (optional)"
|
|
222
|
+
/>
|
|
223
|
+
</View>
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
### With A/B Testing
|
|
229
|
+
|
|
230
|
+
```typescript
|
|
231
|
+
function ABTestedFeedback() {
|
|
232
|
+
const [showFeedback, setShowFeedback] = useState(false);
|
|
233
|
+
const [variant, setVariant] = useState<'short' | 'long'>('short');
|
|
234
|
+
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
// Determine A/B test variant
|
|
237
|
+
const testVariant = await getABTestVariant('paywall_feedback');
|
|
238
|
+
setVariant(testVariant);
|
|
239
|
+
}, []);
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<PaywallFeedbackModal
|
|
243
|
+
visible={showFeedback}
|
|
244
|
+
onClose={() => setShowFeedback(false)}
|
|
245
|
+
onSubmit={(reason) => {
|
|
246
|
+
analytics.track('paywall_feedback', {
|
|
247
|
+
reason,
|
|
248
|
+
variant,
|
|
249
|
+
abTest: 'paywall_feedback_v1',
|
|
250
|
+
});
|
|
251
|
+
setShowFeedback(false);
|
|
252
|
+
}}
|
|
253
|
+
title={
|
|
254
|
+
variant === 'short'
|
|
255
|
+
? 'Quick Feedback'
|
|
256
|
+
: 'Help Us Improve Our Premium'
|
|
257
|
+
}
|
|
258
|
+
subtitle={
|
|
259
|
+
variant === 'short'
|
|
260
|
+
? 'Why not today?'
|
|
261
|
+
: 'We\'d love to know why you\'re not upgrading'
|
|
262
|
+
}
|
|
263
|
+
submitText={
|
|
264
|
+
variant === 'short'
|
|
265
|
+
? 'Send'
|
|
266
|
+
: 'Submit Feedback'
|
|
267
|
+
}
|
|
268
|
+
/>
|
|
269
|
+
);
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
## Modal Layout
|
|
274
|
+
|
|
275
|
+
```
|
|
276
|
+
┌─────────────────────────────────┐
|
|
277
|
+
│ │
|
|
278
|
+
│ Help Us Improve │
|
|
279
|
+
│ Why are you not upgrading? │
|
|
280
|
+
│ │
|
|
281
|
+
├─────────────────────────────────┤
|
|
282
|
+
│ ○ Too expensive │
|
|
283
|
+
│ ○ Don't need it right now │
|
|
284
|
+
│ ○ Just trying out the app │
|
|
285
|
+
│ ○ Technical issues │
|
|
286
|
+
│ ○ Other │
|
|
287
|
+
│ │
|
|
288
|
+
│ [Text input for Other] │
|
|
289
|
+
│ │
|
|
290
|
+
├─────────────────────────────────┤
|
|
291
|
+
│ [Send Feedback] │
|
|
292
|
+
└─────────────────────────────────┘
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## Best Practices
|
|
296
|
+
|
|
297
|
+
1. **Track feedback** - Send analytics with feedback data
|
|
298
|
+
2. **Show sparingly** - Don't overwhelm users with feedback requests
|
|
299
|
+
3. **Keep optional** - Allow users to skip feedback
|
|
300
|
+
4. **Use data wisely** - Analyze feedback to improve paywall
|
|
301
|
+
5. **Test timing** - Find optimal moment to show feedback
|
|
302
|
+
6. **Localize content** - Translate all strings for i18n
|
|
303
|
+
7. **Keep simple** - Don't ask for too much information
|
|
304
|
+
|
|
305
|
+
## Related Hooks
|
|
306
|
+
|
|
307
|
+
- **usePaywallFeedback** - Hook for feedback logic
|
|
308
|
+
- **usePaywall** - For paywall state management
|
|
309
|
+
- **usePaywallVisibility** - For paywall visibility
|
|
310
|
+
|
|
311
|
+
## See Also
|
|
312
|
+
|
|
313
|
+
- [Paywall Screen](../../screens/README.md)
|
|
314
|
+
- [Feedback Utilities](../../hooks/feedback/usePaywallFeedback.md)
|