@umituz/react-native-subscription 2.39.7 → 2.39.8
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.39.
|
|
3
|
+
"version": "2.39.8",
|
|
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",
|
|
@@ -77,145 +77,157 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
77
77
|
}
|
|
78
78
|
}, []);
|
|
79
79
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
80
|
+
return (
|
|
81
|
+
<View style={[screenStyles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
|
|
82
|
+
{/* Close button - positioned absolutely at top */}
|
|
83
|
+
<View style={[screenStyles.headerContainer, { paddingTop: insets.top }]}>
|
|
84
|
+
<TouchableOpacity
|
|
85
|
+
onPress={onClose}
|
|
86
|
+
style={[screenStyles.closeBtn, { backgroundColor: tokens.colors.surfaceSecondary }]}
|
|
87
|
+
hitSlop={{ top: 10, bottom: 10, left: 10, right: 10 }}
|
|
88
|
+
>
|
|
89
|
+
<AtomicIcon name="close-outline" size="md" customColor={tokens.colors.textPrimary} />
|
|
90
|
+
</TouchableOpacity>
|
|
91
|
+
</View>
|
|
90
92
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
disabled={isProcessing || isLoadingPackages || !selectedPlanId}
|
|
97
|
-
style={[
|
|
98
|
-
styles.cta,
|
|
99
|
-
{ backgroundColor: tokens.colors.primary },
|
|
100
|
-
(isProcessing || isLoadingPackages || !selectedPlanId) && styles.ctaDisabled
|
|
101
|
-
]}
|
|
102
|
-
activeOpacity={0.75}
|
|
93
|
+
{/* Scrollable content */}
|
|
94
|
+
<ScreenLayout
|
|
95
|
+
scrollable={true}
|
|
96
|
+
backgroundColor="transparent"
|
|
97
|
+
contentContainerStyle={{ ...screenStyles.contentContainer, paddingBottom: 120 }}
|
|
103
98
|
>
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
legalUrls={legalUrls}
|
|
111
|
-
isProcessing={isProcessing}
|
|
112
|
-
onRestore={onRestore ? handleRestore : undefined}
|
|
113
|
-
onLegalClick={handleLegalUrl}
|
|
114
|
-
/>
|
|
115
|
-
</View>
|
|
116
|
-
);
|
|
99
|
+
{/* Hero Image */}
|
|
100
|
+
{heroImage && (
|
|
101
|
+
<View style={styles.heroContainer}>
|
|
102
|
+
<Image source={heroImage} style={styles.heroImage} contentFit="cover" transition={0} />
|
|
103
|
+
</View>
|
|
104
|
+
)}
|
|
117
105
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
scrollable={true}
|
|
121
|
-
backgroundColor={tokens.colors.backgroundPrimary}
|
|
122
|
-
header={closeButton}
|
|
123
|
-
footer={footerContent}
|
|
124
|
-
contentContainerStyle={screenStyles.contentContainer}
|
|
125
|
-
>
|
|
126
|
-
{/* Hero Image */}
|
|
127
|
-
{heroImage && (
|
|
128
|
-
<View style={styles.heroContainer}>
|
|
129
|
-
<Image source={heroImage} style={styles.heroImage} contentFit="cover" transition={0} />
|
|
130
|
-
</View>
|
|
131
|
-
)}
|
|
132
|
-
|
|
133
|
-
{/* Header */}
|
|
134
|
-
<View style={styles.header}>
|
|
135
|
-
<AtomicText
|
|
136
|
-
type="headlineMedium"
|
|
137
|
-
adjustsFontSizeToFit
|
|
138
|
-
numberOfLines={2}
|
|
139
|
-
minimumFontScale={0.75}
|
|
140
|
-
style={[styles.title, { color: tokens.colors.textPrimary }]}
|
|
141
|
-
>
|
|
142
|
-
{translations.title}
|
|
143
|
-
</AtomicText>
|
|
144
|
-
{translations.subtitle && (
|
|
106
|
+
{/* Header */}
|
|
107
|
+
<View style={styles.header}>
|
|
145
108
|
<AtomicText
|
|
146
|
-
type="
|
|
109
|
+
type="headlineMedium"
|
|
147
110
|
adjustsFontSizeToFit
|
|
148
|
-
numberOfLines={
|
|
149
|
-
minimumFontScale={0.
|
|
150
|
-
style={[styles.
|
|
111
|
+
numberOfLines={2}
|
|
112
|
+
minimumFontScale={0.75}
|
|
113
|
+
style={[styles.title, { color: tokens.colors.textPrimary }]}
|
|
151
114
|
>
|
|
152
|
-
{translations.
|
|
115
|
+
{translations.title}
|
|
153
116
|
</AtomicText>
|
|
154
|
-
|
|
155
|
-
</View>
|
|
156
|
-
|
|
157
|
-
{/* Features */}
|
|
158
|
-
<PaywallFeatures features={features} />
|
|
159
|
-
|
|
160
|
-
{/* Plans */}
|
|
161
|
-
<View style={styles.plans}>
|
|
162
|
-
{isLoadingPackages ? (
|
|
163
|
-
<View style={styles.loading}>
|
|
164
|
-
<AtomicSpinner size="md" />
|
|
165
|
-
{translations.processingText && (
|
|
166
|
-
<AtomicText
|
|
167
|
-
type="bodySmall"
|
|
168
|
-
style={[styles.loadingText, { color: tokens.colors.textSecondary }]}
|
|
169
|
-
>
|
|
170
|
-
{translations.processingText}
|
|
171
|
-
</AtomicText>
|
|
172
|
-
)}
|
|
173
|
-
</View>
|
|
174
|
-
) : packages.length === 0 ? (
|
|
175
|
-
<View style={styles.loading}>
|
|
117
|
+
{translations.subtitle && (
|
|
176
118
|
<AtomicText
|
|
177
119
|
type="bodyMedium"
|
|
178
|
-
|
|
120
|
+
adjustsFontSizeToFit
|
|
121
|
+
numberOfLines={3}
|
|
122
|
+
minimumFontScale={0.8}
|
|
123
|
+
style={[styles.subtitle, { color: tokens.colors.textSecondary }]}
|
|
179
124
|
>
|
|
180
|
-
{translations.
|
|
125
|
+
{translations.subtitle}
|
|
181
126
|
</AtomicText>
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
127
|
+
)}
|
|
128
|
+
</View>
|
|
129
|
+
|
|
130
|
+
{/* Features */}
|
|
131
|
+
<PaywallFeatures features={features} />
|
|
132
|
+
|
|
133
|
+
{/* Plans */}
|
|
134
|
+
<View style={styles.plans}>
|
|
135
|
+
{isLoadingPackages ? (
|
|
136
|
+
<View style={styles.loading}>
|
|
137
|
+
<AtomicSpinner size="md" />
|
|
138
|
+
{translations.processingText && (
|
|
139
|
+
<AtomicText
|
|
140
|
+
type="bodySmall"
|
|
141
|
+
style={[styles.loadingText, { color: tokens.colors.textSecondary }]}
|
|
142
|
+
>
|
|
143
|
+
{translations.processingText}
|
|
144
|
+
</AtomicText>
|
|
145
|
+
)}
|
|
146
|
+
</View>
|
|
147
|
+
) : packages.length === 0 ? (
|
|
148
|
+
<View style={styles.loading}>
|
|
149
|
+
<AtomicText
|
|
150
|
+
type="bodyMedium"
|
|
151
|
+
style={{ color: tokens.colors.textSecondary, textAlign: "center" }}
|
|
152
|
+
>
|
|
153
|
+
{translations.emptyText ?? "No packages available"}
|
|
154
|
+
</AtomicText>
|
|
155
|
+
</View>
|
|
156
|
+
) : (
|
|
157
|
+
packages.map((pkg) => {
|
|
158
|
+
const pid = pkg.product.identifier;
|
|
159
|
+
const isSelected = selectedPlanId === pid;
|
|
160
|
+
const isBestValue = bestValueIdentifier === pid;
|
|
161
|
+
const credits = creditAmounts?.[pid];
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<PlanCard
|
|
165
|
+
key={pid}
|
|
166
|
+
pkg={pkg}
|
|
167
|
+
isSelected={isSelected}
|
|
168
|
+
badge={isBestValue ? translations.bestValueBadgeText : undefined}
|
|
169
|
+
creditAmount={credits}
|
|
170
|
+
creditsLabel={creditsLabel}
|
|
171
|
+
onSelect={() => setSelectedPlanId(pid)}
|
|
172
|
+
/>
|
|
173
|
+
);
|
|
174
|
+
})
|
|
175
|
+
)}
|
|
176
|
+
</View>
|
|
177
|
+
</ScreenLayout>
|
|
178
|
+
|
|
179
|
+
{/* Fixed footer overlay - always visible at bottom */}
|
|
180
|
+
<View style={[styles.stickyFooter, { backgroundColor: tokens.colors.backgroundPrimary, paddingBottom: Math.max(insets.bottom, 16) }]}>
|
|
181
|
+
<TouchableOpacity
|
|
182
|
+
onPress={handlePurchase}
|
|
183
|
+
disabled={isProcessing || isLoadingPackages || !selectedPlanId}
|
|
184
|
+
style={[
|
|
185
|
+
styles.cta,
|
|
186
|
+
{ backgroundColor: tokens.colors.primary },
|
|
187
|
+
(isProcessing || isLoadingPackages || !selectedPlanId) && styles.ctaDisabled
|
|
188
|
+
]}
|
|
189
|
+
activeOpacity={0.75}
|
|
190
|
+
>
|
|
191
|
+
<AtomicText type="titleLarge" style={[styles.ctaText, { color: tokens.colors.onPrimary }]}>
|
|
192
|
+
{isProcessing ? translations.processingText : translations.purchaseButtonText}
|
|
193
|
+
</AtomicText>
|
|
194
|
+
</TouchableOpacity>
|
|
195
|
+
<PaywallFooter
|
|
196
|
+
translations={translations}
|
|
197
|
+
legalUrls={legalUrls}
|
|
198
|
+
isProcessing={isProcessing}
|
|
199
|
+
onRestore={onRestore ? handleRestore : undefined}
|
|
200
|
+
onLegalClick={handleLegalUrl}
|
|
201
|
+
/>
|
|
203
202
|
</View>
|
|
204
|
-
</
|
|
203
|
+
</View>
|
|
205
204
|
);
|
|
206
205
|
});
|
|
207
206
|
|
|
208
207
|
PaywallScreen.displayName = "PaywallScreen";
|
|
209
208
|
|
|
210
209
|
const screenStyles = StyleSheet.create({
|
|
210
|
+
container: {
|
|
211
|
+
flex: 1,
|
|
212
|
+
},
|
|
213
|
+
headerContainer: {
|
|
214
|
+
position: 'absolute',
|
|
215
|
+
top: 0,
|
|
216
|
+
left: 0,
|
|
217
|
+
right: 0,
|
|
218
|
+
zIndex: 1000,
|
|
219
|
+
paddingHorizontal: 12,
|
|
220
|
+
paddingTop: 12,
|
|
221
|
+
},
|
|
211
222
|
closeBtn: {
|
|
212
223
|
width: 36,
|
|
213
224
|
height: 36,
|
|
214
225
|
borderRadius: 18,
|
|
215
226
|
justifyContent: 'center',
|
|
216
227
|
alignItems: 'center',
|
|
228
|
+
alignSelf: 'flex-end',
|
|
217
229
|
},
|
|
218
230
|
contentContainer: {
|
|
219
|
-
|
|
231
|
+
paddingTop: 60, // Space for close button
|
|
220
232
|
},
|
|
221
233
|
});
|
|
@@ -139,7 +139,13 @@ export const PaywallFeedbackScreen: React.FC<PaywallFeedbackScreenProps> = React
|
|
|
139
139
|
|
|
140
140
|
PaywallFeedbackScreen.displayName = "PaywallFeedbackScreen";
|
|
141
141
|
|
|
142
|
-
const createScreenStyles = (
|
|
142
|
+
const createScreenStyles = (
|
|
143
|
+
tokens: {
|
|
144
|
+
colors: { backgroundPrimary: string; border: string };
|
|
145
|
+
spacing: { xl: number; sm: number; md: number };
|
|
146
|
+
},
|
|
147
|
+
_insets: { top: number; bottom: number }
|
|
148
|
+
) => ({
|
|
143
149
|
container: {
|
|
144
150
|
flex: 1,
|
|
145
151
|
},
|