@umituz/react-native-subscription 2.35.15 → 2.35.17

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.
Files changed (45) hide show
  1. package/package.json +1 -1
  2. package/src/domains/config/utils/planSelectors.ts +5 -1
  3. package/src/domains/credits/presentation/useCredits.ts +6 -5
  4. package/src/domains/paywall/hooks/usePaywallActions.ts +2 -82
  5. package/src/domains/revenuecat/core/customerInfoHelpers.ts +21 -0
  6. package/src/domains/subscription/application/SubscriptionAuthListener.ts +0 -19
  7. package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +1 -1
  8. package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +2 -8
  9. package/src/domains/subscription/application/initializer/ConfigValidator.ts +2 -2
  10. package/src/domains/subscription/application/initializer/ServiceConfigurator.ts +23 -3
  11. package/src/domains/subscription/application/statusChangeHandlers.ts +0 -30
  12. package/src/domains/subscription/constants/thresholds.ts +10 -0
  13. package/src/domains/subscription/infrastructure/handlers/PurchaseStatusResolver.ts +3 -3
  14. package/src/domains/subscription/infrastructure/handlers/package-operations/PackageFetcher.ts +0 -19
  15. package/src/domains/subscription/infrastructure/hooks/customer-info/useCustomerInfo.ts +1 -1
  16. package/src/domains/subscription/infrastructure/hooks/useInitializeSubscription.ts +2 -4
  17. package/src/domains/subscription/infrastructure/hooks/usePaywallFlow.ts +12 -2
  18. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +0 -44
  19. package/src/domains/subscription/infrastructure/hooks/useRevenueCat.ts +23 -5
  20. package/src/domains/subscription/infrastructure/services/CustomerInfoListenerManager.ts +1 -31
  21. package/src/domains/subscription/infrastructure/services/OfferingsFetcher.ts +0 -21
  22. package/src/domains/subscription/infrastructure/services/listeners/CustomerInfoHandler.ts +6 -36
  23. package/src/domains/subscription/infrastructure/services/purchase/PurchaseExecutor.ts +0 -6
  24. package/src/domains/subscription/infrastructure/utils/PremiumStatusSyncer.ts +3 -44
  25. package/src/domains/subscription/presentation/featureGateActions.ts +0 -37
  26. package/src/domains/subscription/presentation/screens/components/SubscriptionHeader.tsx +1 -1
  27. package/src/domains/subscription/presentation/screens/components/SubscriptionHeaderContent.tsx +1 -1
  28. package/src/domains/subscription/presentation/useAuthAwarePurchase.ts +0 -43
  29. package/src/domains/subscription/presentation/useFeatureGate.ts +1 -40
  30. package/src/domains/subscription/presentation/useSubscriptionStatus.ts +6 -20
  31. package/src/domains/subscription/utils/authGuards.ts +26 -2
  32. package/src/domains/subscription/utils/expirationHelpers.ts +2 -2
  33. package/src/domains/trial/application/TrialEligibilityService.ts +1 -1
  34. package/src/domains/trial/application/TrialService.ts +12 -4
  35. package/src/domains/wallet/infrastructure/repositories/transaction/TransactionWriter.ts +1 -1
  36. package/src/domains/wallet/presentation/hooks/useProductMetadata.ts +2 -5
  37. package/src/domains/wallet/presentation/hooks/useTransactionHistory.ts +2 -5
  38. package/src/shared/infrastructure/react-query/hooks/usePreviousUserCleanup.ts +39 -0
  39. package/src/shared/infrastructure/react-query/queryConfig.ts +22 -0
  40. package/src/shared/infrastructure/react-query/queryInvalidation.ts +46 -0
  41. package/src/shared/presentation/hooks/useServiceCall.ts +2 -1
  42. package/src/shared/utils/errorUtils.ts +32 -0
  43. package/src/utils/appUtils.ts +6 -0
  44. package/src/domains/subscription/presentation/components/details/PremiumDetailsCard.constants.ts +0 -1
  45. package/src/domains/subscription/presentation/screens/components/SubscriptionHeader.constants.ts +0 -1
@@ -19,15 +19,12 @@ import { subscriptionStatusQueryKeys } from "../../presentation/useSubscriptionS
19
19
  import { creditsQueryKeys } from "../../../credits/presentation/creditsQueryKeys";
20
20
  import { getErrorMessage } from "../../../revenuecat/core/errors";
21
21
 
22
- declare const __DEV__: boolean;
23
-
24
22
  /** Purchase mutation result - simplified for presentation layer */
25
23
  export interface PurchaseMutationResult {
26
24
  success: boolean;
27
25
  productId: string;
28
26
  }
29
27
 
30
-
31
28
  /**
32
29
  * Purchase a subscription package
33
30
  * Credits are initialized by CustomerInfoListener when entitlement becomes active
@@ -41,26 +38,11 @@ export const usePurchasePackage = () => {
41
38
 
42
39
  return useMutation({
43
40
  mutationFn: async (pkg: PurchasesPackage): Promise<PurchaseMutationResult> => {
44
- if (typeof __DEV__ !== "undefined" && __DEV__) {
45
- console.log("[Purchase] ========================================");
46
- console.log("[Purchase] mutationFn called:", {
47
- productId: pkg.product.identifier,
48
- userId,
49
- isAnonymous,
50
- });
51
- }
52
-
53
41
  if (!userId) {
54
- if (typeof __DEV__ !== "undefined" && __DEV__) {
55
- console.log("[Purchase] ERROR: User not authenticated");
56
- }
57
42
  throw new Error("User not authenticated");
58
43
  }
59
44
 
60
45
  if (isAnonymous) {
61
- if (typeof __DEV__ !== "undefined" && __DEV__) {
62
- console.log("[Purchase] ERROR: Anonymous users cannot purchase");
63
- }
64
46
  throw new Error("Anonymous users cannot purchase subscriptions");
65
47
  }
66
48
 
@@ -71,21 +53,11 @@ export const usePurchasePackage = () => {
71
53
 
72
54
  const success = await SubscriptionManager.purchasePackage(pkg);
73
55
 
74
- if (typeof __DEV__ !== "undefined" && __DEV__) {
75
- console.log("[Purchase] Purchase completed:", { success, productId });
76
- }
77
-
78
56
  return { success, productId };
79
57
  },
80
58
  onSuccess: (result) => {
81
- if (typeof __DEV__ !== "undefined" && __DEV__) {
82
- console.log("[Purchase] onSuccess called:", result);
83
- }
84
59
 
85
60
  if (result.success) {
86
- if (typeof __DEV__ !== "undefined" && __DEV__) {
87
- console.log("[Purchase] ✅ Purchase successful! Invalidating queries...");
88
- }
89
61
  showSuccess("Purchase Successful", "Your subscription is now active!");
90
62
  queryClient.invalidateQueries({
91
63
  queryKey: SUBSCRIPTION_QUERY_KEYS.packages,
@@ -97,34 +69,18 @@ export const usePurchasePackage = () => {
97
69
  queryClient.invalidateQueries({
98
70
  queryKey: creditsQueryKeys.user(userId),
99
71
  });
100
- if (typeof __DEV__ !== "undefined" && __DEV__) {
101
- console.log("[Purchase] Queries invalidated - credits should reload now");
102
- }
103
72
  }
104
73
  } else {
105
- if (typeof __DEV__ !== "undefined" && __DEV__) {
106
- console.log("[Purchase] ❌ Purchase failed");
107
- }
108
74
  showError("Purchase Failed", "Unable to complete purchase. Please try again.");
109
75
  }
110
76
  },
111
77
  onError: (error) => {
112
- if (typeof __DEV__ !== "undefined" && __DEV__) {
113
- console.log("[Purchase] onError called:", error);
114
- }
115
78
 
116
79
  // Use map-based lookup - O(1) complexity
117
80
  const errorInfo = getErrorMessage(error);
118
81
 
119
- if (typeof __DEV__ !== "undefined" && __DEV__) {
120
- console.log("[Purchase] Error info:", errorInfo);
121
- }
122
-
123
82
  // Don't show alert for user cancellation
124
83
  if (!errorInfo.shouldShowAlert) {
125
- if (typeof __DEV__ !== "undefined" && __DEV__) {
126
- console.log("[Purchase] User cancelled - not showing alert");
127
- }
128
84
  return;
129
85
  }
130
86
 
@@ -3,7 +3,7 @@
3
3
  * React hook for RevenueCat subscription management
4
4
  */
5
5
 
6
- import { useState, useCallback } from "react";
6
+ import { useState, useCallback, useEffect, useRef } from "react";
7
7
  import type { PurchasesOffering, PurchasesPackage } from "react-native-purchases";
8
8
  import { getRevenueCatService } from '../../infrastructure/services/RevenueCatService';
9
9
  import type { PurchaseResult, RestoreResult } from '../../../../shared/application/ports/IRevenueCatService';
@@ -35,8 +35,18 @@ export interface UseRevenueCatResult {
35
35
  export function useRevenueCat(): UseRevenueCatResult {
36
36
  const [offering, setOffering] = useState<PurchasesOffering | null>(null);
37
37
  const [loading, setLoading] = useState(false);
38
+ const isMountedRef = useRef(true);
39
+
40
+ useEffect(() => {
41
+ isMountedRef.current = true;
42
+ return () => {
43
+ isMountedRef.current = false;
44
+ };
45
+ }, []);
38
46
 
39
47
  const initialize = useCallback(async (userId: string, apiKey?: string) => {
48
+ if (!isMountedRef.current) return;
49
+
40
50
  setLoading(true);
41
51
  try {
42
52
  const service = getRevenueCatService();
@@ -44,17 +54,21 @@ export function useRevenueCat(): UseRevenueCatResult {
44
54
  return;
45
55
  }
46
56
  const result = await service.initialize(userId, apiKey);
47
- if (result.success) {
57
+ if (result.success && isMountedRef.current) {
48
58
  setOffering(result.offering);
49
59
  }
50
60
  } catch {
51
61
  // Error handling is done by service
52
62
  } finally {
53
- setLoading(false);
63
+ if (isMountedRef.current) {
64
+ setLoading(false);
65
+ }
54
66
  }
55
67
  }, []);
56
68
 
57
69
  const loadOfferings = useCallback(async () => {
70
+ if (!isMountedRef.current) return;
71
+
58
72
  setLoading(true);
59
73
  try {
60
74
  const service = getRevenueCatService();
@@ -62,11 +76,15 @@ export function useRevenueCat(): UseRevenueCatResult {
62
76
  return;
63
77
  }
64
78
  const fetchedOffering = await service.fetchOfferings();
65
- setOffering(fetchedOffering);
79
+ if (isMountedRef.current) {
80
+ setOffering(fetchedOffering);
81
+ }
66
82
  } catch {
67
83
  // Error handling is done by service
68
84
  } finally {
69
- setLoading(false);
85
+ if (isMountedRef.current) {
86
+ setLoading(false);
87
+ }
70
88
  }
71
89
  }, []);
72
90
 
@@ -3,22 +3,12 @@ import type { RevenueCatConfig } from "../../../revenuecat/core/types";
3
3
  import { ListenerState } from "./listeners/ListenerState";
4
4
  import { processCustomerInfo } from "./listeners/CustomerInfoHandler";
5
5
 
6
- declare const __DEV__: boolean;
7
-
8
6
  export class CustomerInfoListenerManager {
9
7
  private state = new ListenerState();
10
8
 
11
9
  setUserId(userId: string, config: RevenueCatConfig): void {
12
10
  const wasUserChange = this.state.hasUserChanged(userId);
13
11
 
14
- if (typeof __DEV__ !== "undefined" && __DEV__) {
15
- console.log("[CustomerInfoListener] setUserId called:", {
16
- userId,
17
- wasUserChange,
18
- hasListener: !!this.state.listener,
19
- });
20
- }
21
-
22
12
  if (wasUserChange) {
23
13
  this.removeListener();
24
14
  this.state.resetRenewalState();
@@ -32,9 +22,6 @@ export class CustomerInfoListenerManager {
32
22
  }
33
23
 
34
24
  clearUserId(): void {
35
- if (typeof __DEV__ !== "undefined" && __DEV__) {
36
- console.log("[CustomerInfoListener] clearUserId called");
37
- }
38
25
  this.state.currentUserId = null;
39
26
  this.state.resetRenewalState();
40
27
  }
@@ -42,10 +29,6 @@ export class CustomerInfoListenerManager {
42
29
  setupListener(config: RevenueCatConfig): void {
43
30
  this.removeListener();
44
31
 
45
- if (typeof __DEV__ !== "undefined" && __DEV__) {
46
- console.log("[CustomerInfoListener] setupListener: Registering listener");
47
- }
48
-
49
32
  this.state.listener = async (customerInfo: CustomerInfo) => {
50
33
  if (typeof __DEV__ !== "undefined" && __DEV__) {
51
34
  console.log("[CustomerInfoListener] 🔔 LISTENER TRIGGERED!", {
@@ -57,9 +40,6 @@ export class CustomerInfoListenerManager {
57
40
 
58
41
  const capturedUserId = this.state.currentUserId;
59
42
  if (!capturedUserId) {
60
- if (typeof __DEV__ !== "undefined" && __DEV__) {
61
- console.log("[CustomerInfoListener] No userId - skipping");
62
- }
63
43
  return;
64
44
  }
65
45
 
@@ -72,21 +52,11 @@ export class CustomerInfoListenerManager {
72
52
 
73
53
  if (this.state.currentUserId === capturedUserId) {
74
54
  this.state.renewalState = newRenewalState;
75
- if (typeof __DEV__ !== "undefined" && __DEV__) {
76
- console.log("[CustomerInfoListener] processCustomerInfo completed");
77
- }
78
- } else {
79
- if (typeof __DEV__ !== "undefined" && __DEV__) {
80
- console.log("[CustomerInfoListener] User changed during processing - discarding result");
81
- }
82
55
  }
56
+ // else: User switched during async operation, discard stale renewal state
83
57
  };
84
58
 
85
59
  Purchases.addCustomerInfoUpdateListener(this.state.listener);
86
-
87
- if (typeof __DEV__ !== "undefined" && __DEV__) {
88
- console.log("[CustomerInfoListener] Listener registered successfully");
89
- }
90
60
  }
91
61
 
92
62
  removeListener(): void {
@@ -4,8 +4,6 @@ export interface OfferingsFetcherDeps {
4
4
  isInitialized: () => boolean;
5
5
  }
6
6
 
7
- declare const __DEV__: boolean;
8
-
9
7
  export async function fetchOfferings(deps: OfferingsFetcherDeps): Promise<PurchasesOffering | null> {
10
8
  if (!deps.isInitialized()) return null;
11
9
  try {
@@ -21,35 +19,16 @@ export async function fetchOfferings(deps: OfferingsFetcherDeps): Promise<Purcha
21
19
  }
22
20
 
23
21
  if (offerings.current) {
24
- if (__DEV__) {
25
- console.log('[OfferingsFetcher] Using current offering:', {
26
- id: offerings.current.identifier,
27
- packagesCount: offerings.current.availablePackages.length,
28
- });
29
- }
30
22
  return offerings.current;
31
23
  }
32
24
 
33
25
  const allOfferings = Object.values(offerings.all);
34
26
  if (allOfferings.length > 0) {
35
- if (__DEV__) {
36
- console.log('[OfferingsFetcher] No current offering, using first from all:', {
37
- id: allOfferings[0].identifier,
38
- packagesCount: allOfferings[0].availablePackages.length,
39
- });
40
- }
41
27
  return allOfferings[0];
42
28
  }
43
29
 
44
- if (__DEV__) {
45
- console.warn('[OfferingsFetcher] No offerings available!');
46
- }
47
-
48
30
  return null;
49
31
  } catch (error) {
50
- if (__DEV__) {
51
- console.error('[OfferingsFetcher] Error:', error);
52
- }
53
32
  throw new Error(`Failed to fetch offerings: ${error instanceof Error ? error.message : "Unknown error"}`);
54
33
  }
55
34
  }
@@ -3,8 +3,6 @@ import type { RevenueCatConfig } from "../../../../revenuecat/core/types";
3
3
  import { syncPremiumStatus } from "../../utils/PremiumStatusSyncer";
4
4
  import { detectRenewal, updateRenewalState, type RenewalState } from "../../utils/renewal";
5
5
 
6
- declare const __DEV__: boolean;
7
-
8
6
  async function handleRenewal(
9
7
  userId: string,
10
8
  productId: string,
@@ -16,12 +14,8 @@ async function handleRenewal(
16
14
 
17
15
  try {
18
16
  await onRenewalDetected(userId, productId, expirationDate, customerInfo);
19
- } catch (error) {
20
- console.error('[CustomerInfoHandler] Renewal detection callback failed', {
21
- userId,
22
- productId,
23
- error
24
- });
17
+ } catch (_error) {
18
+ // Callback errors should not break customer info processing
25
19
  }
26
20
  }
27
21
 
@@ -37,14 +31,8 @@ async function handlePlanChange(
37
31
 
38
32
  try {
39
33
  await onPlanChanged(userId, newProductId, previousProductId, isUpgrade, customerInfo);
40
- } catch (error) {
41
- console.error('[CustomerInfoHandler] Plan change callback failed', {
42
- userId,
43
- newProductId,
44
- previousProductId,
45
- isUpgrade,
46
- error
47
- });
34
+ } catch (_error) {
35
+ // Callback errors should not break customer info processing
48
36
  }
49
37
  }
50
38
 
@@ -55,11 +43,8 @@ async function handlePremiumStatusSync(
55
43
  ): Promise<void> {
56
44
  try {
57
45
  await syncPremiumStatus(config, userId, customerInfo);
58
- } catch (error) {
59
- console.error('[CustomerInfoHandler] Premium status sync failed', {
60
- userId,
61
- error
62
- });
46
+ } catch (_error) {
47
+ // Sync errors are logged by PremiumStatusSyncer, don't break processing
63
48
  }
64
49
  }
65
50
 
@@ -84,19 +69,7 @@ export async function processCustomerInfo(
84
69
  config.entitlementIdentifier
85
70
  );
86
71
 
87
- if (typeof __DEV__ !== "undefined" && __DEV__) {
88
- console.log("[CustomerInfoHandler] Renewal detection result:", {
89
- isRenewal: renewalResult.isRenewal,
90
- isPlanChange: renewalResult.isPlanChange,
91
- productId: renewalResult.productId,
92
- previousProductId: renewalResult.previousProductId,
93
- });
94
- }
95
-
96
72
  if (renewalResult.isRenewal) {
97
- if (typeof __DEV__ !== "undefined" && __DEV__) {
98
- console.log("[CustomerInfoHandler] Handling renewal");
99
- }
100
73
  await handleRenewal(
101
74
  userId,
102
75
  renewalResult.productId!,
@@ -107,9 +80,6 @@ export async function processCustomerInfo(
107
80
  }
108
81
 
109
82
  if (renewalResult.isPlanChange) {
110
- if (typeof __DEV__ !== "undefined" && __DEV__) {
111
- console.log("[CustomerInfoHandler] Handling plan change");
112
- }
113
83
  await handlePlanChange(
114
84
  userId,
115
85
  renewalResult.productId!,
@@ -28,8 +28,6 @@ async function executeConsumablePurchase(
28
28
  };
29
29
  }
30
30
 
31
- declare const __DEV__: boolean;
32
-
33
31
  async function executeSubscriptionPurchase(
34
32
  config: RevenueCatConfig,
35
33
  userId: string,
@@ -59,10 +57,6 @@ async function executeSubscriptionPurchase(
59
57
 
60
58
  await notifyPurchaseCompleted(config, userId, productId, customerInfo, source, packageType);
61
59
 
62
- if (typeof __DEV__ !== "undefined" && __DEV__) {
63
- console.log("[PurchaseExecutor] Purchase flow completed successfully");
64
- }
65
-
66
60
  return {
67
61
  success: true,
68
62
  isPremium,
@@ -8,8 +8,6 @@ import type { RevenueCatConfig, PackageType } from "../../../revenuecat/core/typ
8
8
  import type { PurchaseSource } from "../../../subscription/core/SubscriptionConstants";
9
9
  import { getPremiumEntitlement } from "../../../revenuecat/core/types";
10
10
 
11
- declare const __DEV__: boolean;
12
-
13
11
  export async function syncPremiumStatus(
14
12
  config: RevenueCatConfig,
15
13
  userId: string,
@@ -25,9 +23,6 @@ export async function syncPremiumStatus(
25
23
  }
26
24
 
27
25
  if (!config.onPremiumStatusChanged) {
28
- if (typeof __DEV__ !== "undefined" && __DEV__) {
29
- console.log("[PremiumStatusSyncer] No onPremiumStatusChanged callback - skipping");
30
- }
31
26
  return { success: true };
32
27
  }
33
28
 
@@ -36,21 +31,8 @@ export async function syncPremiumStatus(
36
31
  config.entitlementIdentifier
37
32
  );
38
33
 
39
- if (typeof __DEV__ !== "undefined" && __DEV__) {
40
- console.log("[PremiumStatusSyncer] Premium entitlement:", {
41
- found: !!premiumEntitlement,
42
- productId: premiumEntitlement?.productIdentifier,
43
- expirationDate: premiumEntitlement?.expirationDate,
44
- willRenew: premiumEntitlement?.willRenew,
45
- periodType: premiumEntitlement?.periodType,
46
- });
47
- }
48
-
49
34
  try {
50
35
  if (premiumEntitlement) {
51
- if (typeof __DEV__ !== "undefined" && __DEV__) {
52
- console.log("[PremiumStatusSyncer] Calling onPremiumStatusChanged with premium=true");
53
- }
54
36
  await config.onPremiumStatusChanged(
55
37
  userId,
56
38
  true,
@@ -60,22 +42,11 @@ export async function syncPremiumStatus(
60
42
  premiumEntitlement.periodType as "NORMAL" | "INTRO" | "TRIAL" | undefined
61
43
  );
62
44
  } else {
63
- if (typeof __DEV__ !== "undefined" && __DEV__) {
64
- console.log("[PremiumStatusSyncer] Calling onPremiumStatusChanged with premium=false");
65
- }
66
45
  await config.onPremiumStatusChanged(userId, false, undefined, undefined, undefined, undefined);
67
46
  }
68
- if (typeof __DEV__ !== "undefined" && __DEV__) {
69
- console.log("[PremiumStatusSyncer] onPremiumStatusChanged completed successfully");
70
- }
71
47
  return { success: true };
72
48
  } catch (error) {
73
- console.error('[PremiumStatusSyncer] Premium status change callback failed', {
74
- userId,
75
- isPremium: !!premiumEntitlement,
76
- productId: premiumEntitlement?.productIdentifier,
77
- error
78
- });
49
+
79
50
  return {
80
51
  success: false,
81
52
  error: error instanceof Error ? error : new Error(String(error))
@@ -97,14 +68,7 @@ export async function notifyPurchaseCompleted(
97
68
 
98
69
  try {
99
70
  await config.onPurchaseCompleted(userId, productId, customerInfo, source, packageType);
100
- } catch (error) {
101
- console.error('[PremiumStatusSyncer] Purchase completion callback failed', {
102
- userId,
103
- productId,
104
- source,
105
- packageType,
106
- error
107
- });
71
+ } catch (_error) {
108
72
  // Silently fail callback notifications to prevent crashing the main flow
109
73
  }
110
74
  }
@@ -121,12 +85,7 @@ export async function notifyRestoreCompleted(
121
85
 
122
86
  try {
123
87
  await config.onRestoreCompleted(userId, isPremium, customerInfo);
124
- } catch (error) {
125
- console.error('[PremiumStatusSyncer] Restore completion callback failed', {
126
- userId,
127
- isPremium,
128
- error
129
- });
88
+ } catch (_error) {
130
89
  // Silently fail callback notifications to prevent crashing the main flow
131
90
  }
132
91
  }
@@ -1,7 +1,5 @@
1
1
  import type { MutableRefObject } from "react";
2
2
 
3
- declare const __DEV__: boolean;
4
-
5
3
  export const executeFeatureAction = (
6
4
  action: () => void | Promise<void>,
7
5
  isAuthenticated: boolean,
@@ -15,45 +13,20 @@ export const executeFeatureAction = (
15
13
  isWaitingForPurchaseRef: MutableRefObject<boolean>,
16
14
  isCreditsLoadedRef: MutableRefObject<boolean>
17
15
  ): boolean => {
18
- if (typeof __DEV__ !== "undefined" && __DEV__) {
19
- console.log("[FeatureGate] executeFeatureAction called:", {
20
- isAuthenticated,
21
- hasSubscription: hasSubscriptionRef.current,
22
- creditBalance: creditBalanceRef.current,
23
- requiredCredits: requiredCreditsRef.current,
24
- isCreditsLoaded: isCreditsLoadedRef.current,
25
- });
26
- }
27
16
 
28
17
  if (!isAuthenticated) {
29
- if (typeof __DEV__ !== "undefined" && __DEV__) {
30
- console.log("[FeatureGate] User not authenticated, showing auth modal");
31
- }
32
18
  const postAuthAction = () => {
33
- if (typeof __DEV__ !== "undefined" && __DEV__) {
34
- console.log("[FeatureGate] Post-auth action called");
35
- }
36
19
  if (hasSubscriptionRef.current || creditBalanceRef.current >= requiredCreditsRef.current) {
37
- if (typeof __DEV__ !== "undefined" && __DEV__) {
38
- console.log("[FeatureGate] Post-auth: User has access, executing action");
39
- }
40
20
  action();
41
21
  return;
42
22
  }
43
23
 
44
24
  if (isCreditsLoadedRef.current) {
45
- if (typeof __DEV__ !== "undefined" && __DEV__) {
46
- console.log("[FeatureGate] Post-auth: Credits loaded, showing paywall");
47
- }
48
25
  pendingActionRef.current = action;
49
26
  isWaitingForPurchaseRef.current = true;
50
27
  onShowPaywallRef.current(requiredCreditsRef.current);
51
28
  return;
52
29
  }
53
-
54
- if (typeof __DEV__ !== "undefined" && __DEV__) {
55
- console.log("[FeatureGate] Post-auth: Waiting for credits to load");
56
- }
57
30
  pendingActionRef.current = action;
58
31
  isWaitingForAuthCreditsRef.current = true;
59
32
  };
@@ -62,26 +35,16 @@ export const executeFeatureAction = (
62
35
  }
63
36
 
64
37
  if (hasSubscriptionRef.current) {
65
- if (typeof __DEV__ !== "undefined" && __DEV__) {
66
- console.log("[FeatureGate] User has subscription, executing action");
67
- }
68
38
  action();
69
39
  return true;
70
40
  }
71
41
 
72
42
  if (creditBalanceRef.current < requiredCreditsRef.current) {
73
- if (typeof __DEV__ !== "undefined" && __DEV__) {
74
- console.log("[FeatureGate] Insufficient credits, showing paywall");
75
- }
76
43
  pendingActionRef.current = action;
77
44
  isWaitingForPurchaseRef.current = true;
78
45
  onShowPaywallRef.current(requiredCreditsRef.current);
79
46
  return false;
80
47
  }
81
-
82
- if (typeof __DEV__ !== "undefined" && __DEV__) {
83
- console.log("[FeatureGate] User has enough credits, executing action");
84
- }
85
48
  action();
86
49
  return true;
87
50
  };
@@ -4,7 +4,7 @@ import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-syst
4
4
  import { PremiumStatusBadge } from "../../components/details/PremiumStatusBadge";
5
5
  import type { SubscriptionHeaderProps } from "./SubscriptionHeader.types";
6
6
  import { createSubscriptionHeaderStyles } from "./SubscriptionHeader.styles";
7
- import { EXPIRING_SOON_THRESHOLD_DAYS } from "./SubscriptionHeader.constants";
7
+ import { EXPIRATION_WARNING_THRESHOLD_DAYS as EXPIRING_SOON_THRESHOLD_DAYS } from "../../../constants/thresholds";
8
8
  import { SubscriptionHeaderContent } from "./SubscriptionHeaderContent";
9
9
 
10
10
  export type { SubscriptionHeaderProps } from "./SubscriptionHeader.types";
@@ -31,7 +31,7 @@ export const SubscriptionHeaderContent: React.FC<SubscriptionHeaderContentProps>
31
31
  translations,
32
32
  styles,
33
33
  willRenew,
34
- periodType,
34
+ periodType: _periodType,
35
35
  packageType,
36
36
  store,
37
37
  originalPurchaseDate,
@@ -9,8 +9,6 @@ import { usePremium } from "./usePremium";
9
9
  import type { PurchaseSource } from "../core/SubscriptionConstants";
10
10
  import { authPurchaseStateManager } from "../infrastructure/utils/authPurchaseState";
11
11
 
12
- declare const __DEV__: boolean;
13
-
14
12
  export type { PurchaseAuthProvider } from "../infrastructure/utils/authPurchaseState";
15
13
 
16
14
  export const configureAuthProvider = (provider: import("../infrastructure/utils/authPurchaseState").PurchaseAuthProvider): void => {
@@ -46,84 +44,43 @@ export const useAuthAwarePurchase = (
46
44
 
47
45
  const handlePurchase = useCallback(
48
46
  async (pkg: PurchasesPackage, source?: PurchaseSource): Promise<boolean> => {
49
- if (typeof __DEV__ !== "undefined" && __DEV__) {
50
- console.log("[useAuthAwarePurchase] handlePurchase called", {
51
- productId: pkg.product.identifier,
52
- source: source || params?.source,
53
- });
54
- }
55
47
 
56
48
  const authProvider = authPurchaseStateManager.getProvider();
57
49
 
58
50
  if (!authProvider) {
59
- if (typeof __DEV__ !== "undefined" && __DEV__) {
60
- console.error("[useAuthAwarePurchase] ❌ No auth provider configured");
61
- }
62
51
  return false;
63
52
  }
64
53
 
65
54
  const isAuth = authProvider.isAuthenticated();
66
55
 
67
- if (typeof __DEV__ !== "undefined" && __DEV__) {
68
- console.log("[useAuthAwarePurchase] Auth status:", { isAuth });
69
- }
70
-
71
56
  if (!isAuth) {
72
- if (typeof __DEV__ !== "undefined" && __DEV__) {
73
- console.log("[useAuthAwarePurchase] 🔐 User not authenticated, saving purchase and showing auth modal");
74
- }
75
57
  authPurchaseStateManager.savePurchase(pkg, source || params?.source || "settings");
76
58
  authProvider.showAuthModal();
77
59
  return false;
78
60
  }
79
61
 
80
- if (typeof __DEV__ !== "undefined" && __DEV__) {
81
- console.log("[useAuthAwarePurchase] ✅ User authenticated, proceeding with purchase");
82
- }
83
-
84
62
  const result = await purchasePackage(pkg);
85
63
 
86
- if (typeof __DEV__ !== "undefined" && __DEV__) {
87
- console.log("[useAuthAwarePurchase] Purchase result:", result);
88
- }
89
-
90
64
  return result;
91
65
  },
92
66
  [purchasePackage, params?.source]
93
67
  );
94
68
 
95
69
  const handleRestore = useCallback(async (): Promise<boolean> => {
96
- if (typeof __DEV__ !== "undefined" && __DEV__) {
97
- console.log("[useAuthAwarePurchase] handleRestore called");
98
- }
99
70
 
100
71
  const authProvider = authPurchaseStateManager.getProvider();
101
72
 
102
73
  if (!authProvider) {
103
- if (typeof __DEV__ !== "undefined" && __DEV__) {
104
- console.error("[useAuthAwarePurchase] ❌ No auth provider configured");
105
- }
106
74
  return false;
107
75
  }
108
76
 
109
77
  if (!authProvider.isAuthenticated()) {
110
- if (typeof __DEV__ !== "undefined" && __DEV__) {
111
- console.log("[useAuthAwarePurchase] 🔐 User not authenticated, showing auth modal");
112
- }
113
78
  authProvider.showAuthModal();
114
79
  return false;
115
80
  }
116
81
 
117
- if (typeof __DEV__ !== "undefined" && __DEV__) {
118
- console.log("[useAuthAwarePurchase] ✅ User authenticated, proceeding with restore");
119
- }
120
-
121
82
  const result = await restorePurchase();
122
83
 
123
- if (typeof __DEV__ !== "undefined" && __DEV__) {
124
- console.log("[useAuthAwarePurchase] Restore result:", result);
125
- }
126
-
127
84
  return result;
128
85
  }, [restorePurchase]);
129
86