@umituz/react-native-subscription 2.41.12 → 2.42.0
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 +1 -1
- package/src/domains/paywall/components/PaywallScreen.tsx +16 -8
- package/src/domains/paywall/components/PaywallScreen.types.ts +1 -2
- package/src/domains/paywall/hooks/usePaywallActions.ts +43 -63
- package/src/domains/paywall/hooks/usePaywallOrchestrator.ts +18 -9
- package/src/domains/subscription/presentation/components/ManagedSubscriptionFlow.tsx +4 -2
- package/src/domains/subscription/presentation/usePremium.ts +8 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.42.0",
|
|
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",
|
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
StatusBar,
|
|
15
15
|
} from "react-native";
|
|
16
16
|
import { useNavigation } from "@react-navigation/native";
|
|
17
|
+
import { usePremium } from "../../subscription/presentation/usePremium";
|
|
17
18
|
import { AtomicText, AtomicIcon, AtomicSpinner } from "@umituz/react-native-design-system/atoms";
|
|
18
19
|
import { useSafeAreaInsets } from "@umituz/react-native-design-system/safe-area";
|
|
19
20
|
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
@@ -32,6 +33,15 @@ import { hasItems } from "../../../shared/utils/arrayUtils";
|
|
|
32
33
|
export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) => {
|
|
33
34
|
const navigation = useNavigation();
|
|
34
35
|
|
|
36
|
+
if (__DEV__) {
|
|
37
|
+
console.log('[PaywallScreen] 📱 Rendering PaywallScreen', {
|
|
38
|
+
hasPackages: !!props.packages?.length,
|
|
39
|
+
packagesCount: props.packages?.length || 0,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const { purchasePackage, restorePurchase } = usePremium();
|
|
44
|
+
|
|
35
45
|
const {
|
|
36
46
|
onClose,
|
|
37
47
|
translations,
|
|
@@ -42,8 +52,6 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
42
52
|
creditAmounts,
|
|
43
53
|
creditsLabel,
|
|
44
54
|
heroImage,
|
|
45
|
-
onPurchase,
|
|
46
|
-
onRestore,
|
|
47
55
|
onPurchaseSuccess,
|
|
48
56
|
onPurchaseError,
|
|
49
57
|
onAuthRequired,
|
|
@@ -54,8 +62,8 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
54
62
|
const tokens = useAppDesignTokens();
|
|
55
63
|
const insets = useSafeAreaInsets();
|
|
56
64
|
|
|
57
|
-
// Default close handler using navigation
|
|
58
65
|
const handleClose = useCallback(() => {
|
|
66
|
+
if (__DEV__) console.log('[PaywallScreen] 🔙 Closing paywall');
|
|
59
67
|
if (onClose) {
|
|
60
68
|
onClose();
|
|
61
69
|
} else if (navigation.canGoBack()) {
|
|
@@ -72,8 +80,8 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
72
80
|
resetState
|
|
73
81
|
} = usePaywallActions({
|
|
74
82
|
packages,
|
|
75
|
-
|
|
76
|
-
|
|
83
|
+
purchasePackage,
|
|
84
|
+
restorePurchase,
|
|
77
85
|
source,
|
|
78
86
|
onPurchaseSuccess,
|
|
79
87
|
onPurchaseError,
|
|
@@ -81,9 +89,9 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
81
89
|
onClose: handleClose
|
|
82
90
|
});
|
|
83
91
|
|
|
84
|
-
// Reset state when screen is closed to avoid lockups
|
|
85
92
|
useEffect(() => {
|
|
86
93
|
return () => {
|
|
94
|
+
if (__DEV__) console.log('[PaywallScreen] 🧹 Cleanup: resetting state');
|
|
87
95
|
resetState();
|
|
88
96
|
};
|
|
89
97
|
}, [resetState]);
|
|
@@ -209,7 +217,7 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
209
217
|
|
|
210
218
|
|
|
211
219
|
// Performance Optimization: getItemLayout for FlatList
|
|
212
|
-
const getItemLayout = useCallback((_data:
|
|
220
|
+
const getItemLayout = useCallback((_data: ArrayLike<PaywallListItem> | null, index: number) => {
|
|
213
221
|
return calculatePaywallItemLayout(flatData, index);
|
|
214
222
|
}, [flatData]);
|
|
215
223
|
|
|
@@ -303,7 +311,7 @@ export const PaywallScreen: React.FC<PaywallScreenProps> = React.memo((props) =>
|
|
|
303
311
|
translations={translations}
|
|
304
312
|
legalUrls={legalUrls}
|
|
305
313
|
isProcessing={isProcessing}
|
|
306
|
-
onRestore={
|
|
314
|
+
onRestore={handleRestore}
|
|
307
315
|
onLegalClick={handleLegalUrl}
|
|
308
316
|
/>
|
|
309
317
|
</View>
|
|
@@ -13,8 +13,7 @@ export interface PaywallScreenProps {
|
|
|
13
13
|
creditAmounts?: Record<string, number>;
|
|
14
14
|
creditsLabel?: string;
|
|
15
15
|
heroImage?: ImageSourcePropType;
|
|
16
|
-
|
|
17
|
-
onRestore?: () => Promise<void | boolean>;
|
|
16
|
+
// Purchase/restore handlers removed - always use usePremium hook internally
|
|
18
17
|
onPurchaseSuccess?: () => void;
|
|
19
18
|
onPurchaseError?: (error: Error | string) => void;
|
|
20
19
|
onAuthRequired?: () => void;
|
|
@@ -7,8 +7,8 @@ import { useCredits } from "../../credits/presentation/useCredits";
|
|
|
7
7
|
|
|
8
8
|
interface UsePaywallActionsParams {
|
|
9
9
|
packages?: PurchasesPackage[];
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
purchasePackage: (pkg: PurchasesPackage) => Promise<boolean>;
|
|
11
|
+
restorePurchase: () => Promise<boolean>;
|
|
12
12
|
source?: PurchaseSource;
|
|
13
13
|
onPurchaseSuccess?: () => void;
|
|
14
14
|
onPurchaseError?: (error: Error | string) => void;
|
|
@@ -18,8 +18,8 @@ interface UsePaywallActionsParams {
|
|
|
18
18
|
|
|
19
19
|
export function usePaywallActions({
|
|
20
20
|
packages = [],
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
purchasePackage,
|
|
22
|
+
restorePurchase,
|
|
23
23
|
onPurchaseSuccess,
|
|
24
24
|
onPurchaseError,
|
|
25
25
|
onAuthRequired,
|
|
@@ -28,33 +28,26 @@ export function usePaywallActions({
|
|
|
28
28
|
const [selectedPlanId, setSelectedPlanId] = useState<string | null>(null);
|
|
29
29
|
const [isLocalProcessing, setIsLocalProcessing] = useState(false);
|
|
30
30
|
|
|
31
|
-
// Use optimized selector for global purchasing state
|
|
32
31
|
const isGlobalPurchasing = usePurchaseLoadingStore(selectIsPurchasing);
|
|
33
|
-
|
|
34
|
-
// Get premium and credits status for fallback success checks
|
|
35
32
|
const { refetch: refetchStatus } = useSubscriptionStatus();
|
|
36
33
|
const { refetch: refetchCredits } = useCredits();
|
|
37
|
-
|
|
38
|
-
// Combine processing states
|
|
34
|
+
|
|
39
35
|
const isProcessing = isLocalProcessing || isGlobalPurchasing;
|
|
40
|
-
|
|
41
|
-
// Use ref for isProcessing to keep callbacks stable without re-creating them
|
|
42
36
|
const isProcessingRef = useRef(isProcessing);
|
|
43
37
|
isProcessingRef.current = isProcessing;
|
|
44
38
|
|
|
45
39
|
const { startPurchase, endPurchase } = usePurchaseLoadingStore();
|
|
46
40
|
|
|
47
|
-
const
|
|
48
|
-
const
|
|
41
|
+
const purchasePackageRef = useRef(purchasePackage);
|
|
42
|
+
const restorePurchaseRef = useRef(restorePurchase);
|
|
49
43
|
const onPurchaseSuccessRef = useRef(onPurchaseSuccess);
|
|
50
44
|
const onPurchaseErrorRef = useRef(onPurchaseError);
|
|
51
45
|
const onAuthRequiredRef = useRef(onAuthRequired);
|
|
52
46
|
const onCloseRef = useRef(onClose);
|
|
53
47
|
const packagesRef = useRef(packages);
|
|
54
48
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
onRestoreRef.current = onRestore;
|
|
49
|
+
purchasePackageRef.current = purchasePackage;
|
|
50
|
+
restorePurchaseRef.current = restorePurchase;
|
|
58
51
|
onPurchaseSuccessRef.current = onPurchaseSuccess;
|
|
59
52
|
onPurchaseErrorRef.current = onPurchaseError;
|
|
60
53
|
onAuthRequiredRef.current = onAuthRequired;
|
|
@@ -62,29 +55,20 @@ export function usePaywallActions({
|
|
|
62
55
|
packagesRef.current = packages;
|
|
63
56
|
|
|
64
57
|
const handlePurchase = useCallback(async () => {
|
|
65
|
-
// Access current state via refs to keep callback stable
|
|
66
58
|
const currentSelectedId = selectedPlanId;
|
|
67
59
|
if (!currentSelectedId) return;
|
|
68
60
|
|
|
69
|
-
if (!onPurchaseRef.current) {
|
|
70
|
-
onPurchaseErrorRef.current?.(new Error("Purchase handler not configured"));
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
61
|
if (isProcessingRef.current) return;
|
|
75
62
|
|
|
76
63
|
const pkg = packagesRef.current.find((p) => p.product.identifier === currentSelectedId);
|
|
77
|
-
|
|
78
64
|
if (!pkg) {
|
|
79
65
|
onPurchaseErrorRef.current?.(new Error(`Package not found: ${currentSelectedId}`));
|
|
80
66
|
return;
|
|
81
67
|
}
|
|
82
68
|
|
|
83
69
|
if (__DEV__) {
|
|
84
|
-
console.log('[usePaywallActions] Starting purchase', {
|
|
70
|
+
console.log('[usePaywallActions] 🛒 Starting purchase', {
|
|
85
71
|
productId: pkg.product.identifier,
|
|
86
|
-
hasOnClose: !!onCloseRef.current,
|
|
87
|
-
hasOnSuccess: !!onPurchaseSuccessRef.current,
|
|
88
72
|
});
|
|
89
73
|
}
|
|
90
74
|
|
|
@@ -92,87 +76,77 @@ export function usePaywallActions({
|
|
|
92
76
|
startPurchase(currentSelectedId, "manual");
|
|
93
77
|
|
|
94
78
|
try {
|
|
95
|
-
const success = await
|
|
79
|
+
const success = await purchasePackageRef.current(pkg);
|
|
80
|
+
|
|
96
81
|
if (__DEV__) {
|
|
97
|
-
console.log('[usePaywallActions] Purchase completed', { success });
|
|
82
|
+
console.log('[usePaywallActions] ✅ Purchase completed', { success });
|
|
98
83
|
}
|
|
99
84
|
|
|
100
|
-
// Check if purchase was successful
|
|
101
|
-
// We consider it success if:
|
|
102
|
-
// 1. Handler returns true
|
|
103
|
-
// 2. Handler returns void (undefined) but user is now premium (fallback for misconfigured handlers)
|
|
104
85
|
let isActuallySuccessful = success === true;
|
|
105
|
-
|
|
86
|
+
|
|
106
87
|
if (success === undefined) {
|
|
107
88
|
if (__DEV__) {
|
|
108
|
-
console.log('[usePaywallActions]
|
|
89
|
+
console.log('[usePaywallActions] 🔍 Checking premium status as fallback...');
|
|
109
90
|
}
|
|
110
|
-
|
|
111
|
-
// Use Promise.all to fetch both in parallel
|
|
91
|
+
|
|
112
92
|
const [statusResult, creditsResult] = await Promise.all([
|
|
113
93
|
refetchStatus(),
|
|
114
94
|
refetchCredits()
|
|
115
95
|
]);
|
|
116
|
-
|
|
96
|
+
|
|
117
97
|
const isSubscriptionPremium = statusResult.data?.isPremium ?? false;
|
|
118
98
|
const isCreditsPremium = creditsResult.data?.isPremium ?? false;
|
|
119
|
-
|
|
99
|
+
|
|
120
100
|
isActuallySuccessful = isSubscriptionPremium || isCreditsPremium;
|
|
121
|
-
|
|
101
|
+
|
|
122
102
|
if (__DEV__) {
|
|
123
|
-
console.log('[usePaywallActions] Fallback check result:', {
|
|
124
|
-
isSubscriptionPremium,
|
|
125
|
-
isCreditsPremium,
|
|
126
|
-
isActuallySuccessful
|
|
103
|
+
console.log('[usePaywallActions] 📊 Fallback check result:', {
|
|
104
|
+
isSubscriptionPremium,
|
|
105
|
+
isCreditsPremium,
|
|
106
|
+
isActuallySuccessful
|
|
127
107
|
});
|
|
128
108
|
}
|
|
129
109
|
}
|
|
130
110
|
|
|
131
111
|
if (isActuallySuccessful) {
|
|
132
112
|
if (__DEV__) {
|
|
133
|
-
console.log('[usePaywallActions] Purchase successful,
|
|
113
|
+
console.log('[usePaywallActions] 🎉 Purchase successful, closing paywall');
|
|
134
114
|
}
|
|
135
115
|
onPurchaseSuccessRef.current?.();
|
|
136
|
-
// Always close paywall on successful purchase
|
|
137
116
|
onCloseRef.current?.();
|
|
138
117
|
} else {
|
|
139
118
|
if (__DEV__) {
|
|
140
|
-
console.warn('[usePaywallActions] Purchase did not indicate success
|
|
119
|
+
console.warn('[usePaywallActions] ⚠️ Purchase did not indicate success');
|
|
141
120
|
}
|
|
142
121
|
}
|
|
143
122
|
} catch (error) {
|
|
123
|
+
if (__DEV__) {
|
|
124
|
+
console.error('[usePaywallActions] ❌ Purchase error:', error);
|
|
125
|
+
}
|
|
144
126
|
onPurchaseErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
|
|
145
127
|
} finally {
|
|
146
128
|
setIsLocalProcessing(false);
|
|
147
129
|
endPurchase(currentSelectedId);
|
|
148
130
|
}
|
|
149
|
-
}, [selectedPlanId, startPurchase, endPurchase, refetchStatus, refetchCredits]);
|
|
131
|
+
}, [selectedPlanId, startPurchase, endPurchase, refetchStatus, refetchCredits]);
|
|
150
132
|
|
|
151
133
|
const handleRestore = useCallback(async () => {
|
|
152
|
-
if (!onRestoreRef.current) {
|
|
153
|
-
onPurchaseErrorRef.current?.(new Error("Restore handler not configured"));
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
134
|
if (isProcessingRef.current) return;
|
|
158
135
|
|
|
159
136
|
if (__DEV__) {
|
|
160
|
-
console.log('[usePaywallActions] Starting restore'
|
|
161
|
-
hasOnClose: !!onCloseRef.current,
|
|
162
|
-
hasOnSuccess: !!onPurchaseSuccessRef.current,
|
|
163
|
-
});
|
|
137
|
+
console.log('[usePaywallActions] 🔄 Starting restore');
|
|
164
138
|
}
|
|
165
139
|
|
|
166
140
|
setIsLocalProcessing(true);
|
|
167
141
|
try {
|
|
168
|
-
const success = await
|
|
142
|
+
const success = await restorePurchaseRef.current();
|
|
143
|
+
|
|
169
144
|
if (__DEV__) {
|
|
170
|
-
console.log('[usePaywallActions] Restore completed', { success });
|
|
145
|
+
console.log('[usePaywallActions] ✅ Restore completed', { success });
|
|
171
146
|
}
|
|
172
147
|
|
|
173
|
-
// Check success with same fallback as purchase
|
|
174
148
|
let isActuallySuccessful = success === true;
|
|
175
|
-
|
|
149
|
+
|
|
176
150
|
if (success === undefined) {
|
|
177
151
|
const [statusResult, creditsResult] = await Promise.all([
|
|
178
152
|
refetchStatus(),
|
|
@@ -183,23 +157,29 @@ export function usePaywallActions({
|
|
|
183
157
|
|
|
184
158
|
if (isActuallySuccessful) {
|
|
185
159
|
if (__DEV__) {
|
|
186
|
-
console.log('[usePaywallActions] Restore successful,
|
|
160
|
+
console.log('[usePaywallActions] 🎉 Restore successful, closing paywall');
|
|
187
161
|
}
|
|
188
162
|
onPurchaseSuccessRef.current?.();
|
|
189
163
|
onCloseRef.current?.();
|
|
190
164
|
} else {
|
|
191
165
|
if (__DEV__) {
|
|
192
|
-
console.warn('[usePaywallActions] Restore did not indicate success
|
|
166
|
+
console.warn('[usePaywallActions] ⚠️ Restore did not indicate success');
|
|
193
167
|
}
|
|
194
168
|
}
|
|
195
169
|
} catch (error) {
|
|
170
|
+
if (__DEV__) {
|
|
171
|
+
console.error('[usePaywallActions] ❌ Restore error:', error);
|
|
172
|
+
}
|
|
196
173
|
onPurchaseErrorRef.current?.(error instanceof Error ? error : new Error(String(error)));
|
|
197
174
|
} finally {
|
|
198
175
|
setIsLocalProcessing(false);
|
|
199
176
|
}
|
|
200
|
-
}, [refetchStatus, refetchCredits]);
|
|
177
|
+
}, [refetchStatus, refetchCredits]);
|
|
201
178
|
|
|
202
179
|
const resetState = useCallback(() => {
|
|
180
|
+
if (__DEV__) {
|
|
181
|
+
console.log('[usePaywallActions] 🧹 Resetting state');
|
|
182
|
+
}
|
|
203
183
|
setSelectedPlanId(null);
|
|
204
184
|
setIsLocalProcessing(false);
|
|
205
185
|
}, []);
|
|
@@ -1,15 +1,17 @@
|
|
|
1
|
-
import { useEffect,
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
|
+
import type { NavigationProp } from "@react-navigation/native";
|
|
3
|
+
import type { ImageSourcePropType } from "react-native";
|
|
2
4
|
import { usePremium } from "../../subscription/presentation/usePremium";
|
|
3
5
|
import { useSubscriptionFlowStore } from "../../subscription/presentation/useSubscriptionFlow";
|
|
4
6
|
import { usePaywallVisibility } from "../../subscription/presentation/usePaywallVisibility";
|
|
5
7
|
import { PaywallTranslations, PaywallLegalUrls, SubscriptionFeature } from "../entities/types";
|
|
6
8
|
|
|
7
9
|
export interface PaywallOrchestratorOptions {
|
|
8
|
-
navigation: any
|
|
10
|
+
navigation: NavigationProp<any>;
|
|
9
11
|
translations: PaywallTranslations;
|
|
10
12
|
features: SubscriptionFeature[];
|
|
11
13
|
legalUrls: PaywallLegalUrls;
|
|
12
|
-
heroImage:
|
|
14
|
+
heroImage: ImageSourcePropType;
|
|
13
15
|
isNavReady?: boolean;
|
|
14
16
|
isLocalizationReady?: boolean;
|
|
15
17
|
onAuthRequired?: () => void;
|
|
@@ -36,11 +38,12 @@ export function usePaywallOrchestrator({
|
|
|
36
38
|
bestValueIdentifier = "yearly",
|
|
37
39
|
creditsLabel,
|
|
38
40
|
}: PaywallOrchestratorOptions) {
|
|
41
|
+
// Sadece isPremium ve packages alıyoruz
|
|
42
|
+
// purchasePackage ve restoreRestore fonksiyonlarını ALMIYORUZ
|
|
43
|
+
// Çünkü PaywallScreen zaten usePremium hook'unu doğrudan kullanıyor
|
|
39
44
|
const {
|
|
40
45
|
isPremium,
|
|
41
|
-
packages
|
|
42
|
-
purchasePackage,
|
|
43
|
-
restorePurchase
|
|
46
|
+
packages
|
|
44
47
|
} = usePremium();
|
|
45
48
|
|
|
46
49
|
// Selectors for stable references and fine-grained updates
|
|
@@ -54,7 +57,6 @@ export function usePaywallOrchestrator({
|
|
|
54
57
|
const setShowFeedback = useSubscriptionFlowStore((state) => state.setShowFeedback);
|
|
55
58
|
|
|
56
59
|
const { showPaywall, closePaywall } = usePaywallVisibility();
|
|
57
|
-
const purchasedRef = useRef(false);
|
|
58
60
|
const hasNavigatedRef = useRef(false);
|
|
59
61
|
|
|
60
62
|
useEffect(() => {
|
|
@@ -74,10 +76,13 @@ export function usePaywallOrchestrator({
|
|
|
74
76
|
if (hasNavigatedRef.current) return;
|
|
75
77
|
hasNavigatedRef.current = true;
|
|
76
78
|
|
|
77
|
-
if (__DEV__) console.log('[usePaywallOrchestrator] 🚀 Navigating to Paywall', {
|
|
78
|
-
source: shouldShowPostOnboarding ? "onboarding" : "manual"
|
|
79
|
+
if (__DEV__) console.log('[usePaywallOrchestrator] 🚀 Navigating to Paywall', {
|
|
80
|
+
source: shouldShowPostOnboarding ? "onboarding" : "manual",
|
|
81
|
+
packagesCount: packages.length
|
|
79
82
|
});
|
|
80
83
|
|
|
84
|
+
// SADECE DATA geçiyoruz - FONKSİYON YOK
|
|
85
|
+
// PaywallScreen kendi usePremium hook'unu kullanacak
|
|
81
86
|
navigation.navigate("PaywallScreen", {
|
|
82
87
|
translations,
|
|
83
88
|
legalUrls,
|
|
@@ -87,6 +92,8 @@ export function usePaywallOrchestrator({
|
|
|
87
92
|
heroImage,
|
|
88
93
|
source: shouldShowPostOnboarding ? "onboarding" : "manual",
|
|
89
94
|
packages,
|
|
95
|
+
onPurchaseSuccess,
|
|
96
|
+
onAuthRequired,
|
|
90
97
|
});
|
|
91
98
|
|
|
92
99
|
if (shouldShowPostOnboarding) {
|
|
@@ -119,6 +126,8 @@ export function usePaywallOrchestrator({
|
|
|
119
126
|
closePaywall,
|
|
120
127
|
bestValueIdentifier,
|
|
121
128
|
creditsLabel,
|
|
129
|
+
onPurchaseSuccess,
|
|
130
|
+
onAuthRequired,
|
|
122
131
|
]);
|
|
123
132
|
|
|
124
133
|
const completeOnboarding = useSubscriptionFlowStore((state) => state.completeOnboarding);
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import React, { useState, useEffect } from "react";
|
|
2
|
+
import type { NavigationProp } from "@react-navigation/native";
|
|
3
|
+
import type { ImageSourcePropType } from "react-native";
|
|
2
4
|
import { SplashScreen, useSplashFlow } from "@umituz/react-native-design-system/molecules";
|
|
3
5
|
import { OnboardingScreen } from "@umituz/react-native-design-system/onboarding";
|
|
4
6
|
import { OfflineBanner } from "@umituz/react-native-design-system/offline";
|
|
@@ -11,7 +13,7 @@ import { usePaywallFeedbackSubmit } from "../../../../presentation/hooks/feedbac
|
|
|
11
13
|
|
|
12
14
|
export interface ManagedSubscriptionFlowProps {
|
|
13
15
|
children: React.ReactNode;
|
|
14
|
-
navigation: any
|
|
16
|
+
navigation: NavigationProp<any>;
|
|
15
17
|
islocalizationReady: boolean;
|
|
16
18
|
|
|
17
19
|
// Splash Configuration
|
|
@@ -40,7 +42,7 @@ export interface ManagedSubscriptionFlowProps {
|
|
|
40
42
|
translations: PaywallTranslations;
|
|
41
43
|
features: SubscriptionFeature[];
|
|
42
44
|
legalUrls: PaywallLegalUrls;
|
|
43
|
-
heroImage:
|
|
45
|
+
heroImage: ImageSourcePropType;
|
|
44
46
|
bestValueIdentifier?: string;
|
|
45
47
|
creditsLabel?: string;
|
|
46
48
|
onAuthRequired?: () => void;
|
|
@@ -14,7 +14,6 @@ import { UsePremiumResult } from './usePremium.types';
|
|
|
14
14
|
const EMPTY_PACKAGES: PurchasesPackage[] = [];
|
|
15
15
|
|
|
16
16
|
export const usePremium = (): UsePremiumResult => {
|
|
17
|
-
|
|
18
17
|
const { isPremium: subscriptionActive, isLoading: statusLoading } = useSubscriptionStatus();
|
|
19
18
|
const { credits, isLoading: creditsLoading } = useCredits();
|
|
20
19
|
|
|
@@ -38,7 +37,10 @@ export const usePremium = (): UsePremiumResult => {
|
|
|
38
37
|
try {
|
|
39
38
|
const result = await purchaseMutation.mutateAsync(pkg);
|
|
40
39
|
return result.success;
|
|
41
|
-
} catch {
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (__DEV__) {
|
|
42
|
+
console.error('[usePremium] Purchase failed:', error);
|
|
43
|
+
}
|
|
42
44
|
return false;
|
|
43
45
|
}
|
|
44
46
|
},
|
|
@@ -49,7 +51,10 @@ export const usePremium = (): UsePremiumResult => {
|
|
|
49
51
|
try {
|
|
50
52
|
const result = await restoreMutation.mutateAsync();
|
|
51
53
|
return result.success;
|
|
52
|
-
} catch {
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (__DEV__) {
|
|
56
|
+
console.error('[usePremium] Restore failed:', error);
|
|
57
|
+
}
|
|
53
58
|
return false;
|
|
54
59
|
}
|
|
55
60
|
}, [restoreMutation]);
|