@umituz/react-native-subscription 3.1.25 → 3.1.26
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": "3.1.
|
|
3
|
+
"version": "3.1.26",
|
|
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",
|
|
@@ -12,6 +12,8 @@ interface PaywallFooterProps {
|
|
|
12
12
|
onRestore?: () => Promise<void | boolean>;
|
|
13
13
|
onLegalClick: (url: string | undefined) => void;
|
|
14
14
|
purchaseButtonText?: string;
|
|
15
|
+
isTablet?: boolean;
|
|
16
|
+
isSmallDevice?: boolean;
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
|
|
@@ -22,12 +24,33 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
|
|
|
22
24
|
onRestore,
|
|
23
25
|
onLegalClick,
|
|
24
26
|
purchaseButtonText,
|
|
27
|
+
isTablet = false,
|
|
28
|
+
isSmallDevice = false,
|
|
25
29
|
}) => {
|
|
26
30
|
const tokens = useAppDesignTokens();
|
|
27
31
|
|
|
32
|
+
// Device-based sizing
|
|
33
|
+
const buttonHeight = React.useMemo(() => {
|
|
34
|
+
if (isTablet) return 64; // Larger button on tablet
|
|
35
|
+
if (isSmallDevice) return 52; // Slightly smaller on small phones
|
|
36
|
+
return 56; // Standard size
|
|
37
|
+
}, [isTablet, isSmallDevice]);
|
|
38
|
+
|
|
39
|
+
const fontSize = React.useMemo(() => {
|
|
40
|
+
if (isTablet) return 19;
|
|
41
|
+
if (isSmallDevice) return 16;
|
|
42
|
+
return 17;
|
|
43
|
+
}, [isTablet, isSmallDevice]);
|
|
44
|
+
|
|
45
|
+
const paddingVertical = React.useMemo(() => {
|
|
46
|
+
if (isTablet) return 20;
|
|
47
|
+
if (isSmallDevice) return 12;
|
|
48
|
+
return 16;
|
|
49
|
+
}, [isTablet, isSmallDevice]);
|
|
50
|
+
|
|
28
51
|
return (
|
|
29
52
|
<View style={footerStyles.container}>
|
|
30
|
-
{/* Purchase Button -
|
|
53
|
+
{/* Purchase Button - Device-responsive */}
|
|
31
54
|
{onPurchase && (
|
|
32
55
|
<TouchableOpacity
|
|
33
56
|
onPress={onPurchase}
|
|
@@ -35,7 +58,11 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
|
|
|
35
58
|
activeOpacity={0.8}
|
|
36
59
|
style={[
|
|
37
60
|
footerStyles.purchaseButton,
|
|
38
|
-
{
|
|
61
|
+
{
|
|
62
|
+
backgroundColor: tokens.colors.primary,
|
|
63
|
+
height: buttonHeight,
|
|
64
|
+
paddingVertical: paddingVertical,
|
|
65
|
+
},
|
|
39
66
|
isProcessing && footerStyles.buttonDisabled,
|
|
40
67
|
]}
|
|
41
68
|
>
|
|
@@ -44,20 +71,20 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
|
|
|
44
71
|
<AtomicSpinner size="sm" />
|
|
45
72
|
</View>
|
|
46
73
|
) : (
|
|
47
|
-
<AtomicText style={[footerStyles.purchaseButtonText, { color: tokens.colors.textPrimary }]}>
|
|
74
|
+
<AtomicText style={[footerStyles.purchaseButtonText, { color: tokens.colors.textPrimary, fontSize }]}>
|
|
48
75
|
{purchaseButtonText || translations.purchaseButtonText}
|
|
49
76
|
</AtomicText>
|
|
50
77
|
)}
|
|
51
78
|
</TouchableOpacity>
|
|
52
79
|
)}
|
|
53
80
|
|
|
54
|
-
{/* Restore Link -
|
|
81
|
+
{/* Restore Link - Device-spaced */}
|
|
55
82
|
{onRestore && (
|
|
56
83
|
<TouchableOpacity
|
|
57
84
|
onPress={onRestore}
|
|
58
85
|
disabled={isProcessing}
|
|
59
86
|
activeOpacity={0.6}
|
|
60
|
-
style={footerStyles.restoreButton}
|
|
87
|
+
style={[footerStyles.restoreButton, { marginTop: isTablet ? 16 : 8 }]}
|
|
61
88
|
>
|
|
62
89
|
<AtomicText style={[footerStyles.restoreText, { color: tokens.colors.textSecondary }]}>
|
|
63
90
|
{translations.restoreButtonText}
|
|
@@ -65,7 +92,7 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = React.memo(({
|
|
|
65
92
|
</TouchableOpacity>
|
|
66
93
|
)}
|
|
67
94
|
|
|
68
|
-
{/* Legal Links -
|
|
95
|
+
{/* Legal Links - Responsive spacing */}
|
|
69
96
|
<View style={footerStyles.legalContainer}>
|
|
70
97
|
{legalUrls.termsUrl && (
|
|
71
98
|
<TouchableOpacity
|
|
@@ -105,7 +132,6 @@ const footerStyles = StyleSheet.create({
|
|
|
105
132
|
},
|
|
106
133
|
purchaseButton: {
|
|
107
134
|
width: '100%',
|
|
108
|
-
height: 56,
|
|
109
135
|
borderRadius: 16,
|
|
110
136
|
justifyContent: 'center',
|
|
111
137
|
alignItems: 'center',
|
|
@@ -123,16 +149,13 @@ const footerStyles = StyleSheet.create({
|
|
|
123
149
|
alignItems: 'center',
|
|
124
150
|
},
|
|
125
151
|
purchaseButtonText: {
|
|
126
|
-
fontSize: 17,
|
|
127
152
|
fontWeight: '700',
|
|
128
153
|
letterSpacing: 0.5,
|
|
129
154
|
},
|
|
130
155
|
restoreButton: {
|
|
131
156
|
alignItems: 'center',
|
|
132
|
-
paddingVertical: 4,
|
|
133
157
|
},
|
|
134
158
|
restoreText: {
|
|
135
|
-
fontSize: 13,
|
|
136
159
|
fontWeight: '500',
|
|
137
160
|
textDecorationLine: 'underline',
|
|
138
161
|
},
|
|
@@ -143,11 +166,9 @@ const footerStyles = StyleSheet.create({
|
|
|
143
166
|
flexWrap: 'wrap',
|
|
144
167
|
},
|
|
145
168
|
legalText: {
|
|
146
|
-
fontSize: 11,
|
|
147
169
|
lineHeight: 16,
|
|
148
170
|
},
|
|
149
171
|
legalSeparator: {
|
|
150
|
-
fontSize: 11,
|
|
151
172
|
color: 'rgba(255, 255, 255, 0.4)',
|
|
152
173
|
marginHorizontal: 4,
|
|
153
174
|
},
|
|
@@ -18,6 +18,7 @@ import { useNavigation } from "@react-navigation/native";
|
|
|
18
18
|
import { AtomicIcon, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
|
|
19
19
|
import { useSafeAreaInsets } from "@umituz/react-native-design-system/safe-area";
|
|
20
20
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
21
|
+
import { useResponsive } from "@umituz/react-native-design-system/responsive";
|
|
21
22
|
import { paywallScreenStyles as styles } from "./PaywallScreen.styles";
|
|
22
23
|
import { PaywallFooter } from "./PaywallFooter";
|
|
23
24
|
import { usePaywallActions } from "../hooks/usePaywallActions";
|
|
@@ -61,6 +62,7 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
61
62
|
|
|
62
63
|
const tokens = useAppDesignTokens();
|
|
63
64
|
const insets = useSafeAreaInsets();
|
|
65
|
+
const responsive = useResponsive();
|
|
64
66
|
|
|
65
67
|
const handleClose = useCallback(() => {
|
|
66
68
|
if (__DEV__) console.log('[PaywallScreen] 🔙 Closing paywall');
|
|
@@ -190,11 +192,11 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
190
192
|
<View style={[styles.container, { backgroundColor: tokens.colors.backgroundPrimary }]}>
|
|
191
193
|
<StatusBar barStyle="light-content" />
|
|
192
194
|
|
|
193
|
-
{/* Absolute Close Button */}
|
|
195
|
+
{/* Absolute Close Button - Responsive positioning */}
|
|
194
196
|
<View style={{
|
|
195
197
|
position: 'absolute',
|
|
196
198
|
top: Math.max(insets.top, 16),
|
|
197
|
-
right:
|
|
199
|
+
right: 16,
|
|
198
200
|
zIndex: 10,
|
|
199
201
|
}}>
|
|
200
202
|
<TouchableOpacity
|
|
@@ -206,7 +208,7 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
206
208
|
</TouchableOpacity>
|
|
207
209
|
</View>
|
|
208
210
|
|
|
209
|
-
{/* Main Content */}
|
|
211
|
+
{/* Main Content - Responsive spacing */}
|
|
210
212
|
<FlatList
|
|
211
213
|
data={flatData}
|
|
212
214
|
renderItem={renderItem}
|
|
@@ -220,15 +222,16 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
220
222
|
contentContainerStyle={[
|
|
221
223
|
styles.listContent,
|
|
222
224
|
{
|
|
223
|
-
paddingTop: Math.max(insets.top, 20) +
|
|
224
|
-
paddingBottom: 280 //
|
|
225
|
+
paddingTop: Math.max(insets.top, 20) + 60, // Responsive header spacing
|
|
226
|
+
paddingBottom: 280 + responsive.verticalPadding, // Dynamic footer spacing
|
|
227
|
+
paddingHorizontal: responsive.horizontalPadding, // Device-based horizontal padding
|
|
225
228
|
}
|
|
226
229
|
]}
|
|
227
230
|
showsVerticalScrollIndicator={false}
|
|
228
231
|
/>
|
|
229
232
|
|
|
230
|
-
{/* Fixed Footer -
|
|
231
|
-
<View style={[styles.footerContainer, { paddingBottom: insets.bottom +
|
|
233
|
+
{/* Fixed Footer - Responsive positioning */}
|
|
234
|
+
<View style={[styles.footerContainer, { paddingBottom: insets.bottom + responsive.verticalPadding }]}>
|
|
232
235
|
<PaywallFooter
|
|
233
236
|
translations={translations}
|
|
234
237
|
legalUrls={legalUrls}
|
|
@@ -236,6 +239,8 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
236
239
|
onPurchase={handlePurchase}
|
|
237
240
|
onRestore={handleRestore}
|
|
238
241
|
onLegalClick={handleLegalUrl}
|
|
242
|
+
isTablet={responsive.isTabletDevice}
|
|
243
|
+
isSmallDevice={responsive.isSmallDevice}
|
|
239
244
|
/>
|
|
240
245
|
</View>
|
|
241
246
|
</View>
|