@umituz/react-native-subscription 2.14.68 → 2.14.70

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.14.68",
3
+ "version": "2.14.70",
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",
@@ -4,7 +4,7 @@
4
4
  * Mode: credits | subscription | hybrid
5
5
  */
6
6
 
7
- import React, { useCallback, useEffect, useMemo } from "react";
7
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
8
8
  import type { PurchasesPackage } from "react-native-purchases";
9
9
  import { usePaywallVisibility } from "../../../presentation/hooks/usePaywallVisibility";
10
10
  import { useSubscriptionPackages } from "../../../revenuecat/presentation/hooks/useSubscriptionPackages";
@@ -38,6 +38,10 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = ({
38
38
  const { data: allPackages = [], isLoading, isFetching, status, error } = useSubscriptionPackages(userId ?? undefined);
39
39
  const { mutateAsync: purchasePackage } = usePurchasePackage(userId ?? undefined);
40
40
  const { mutateAsync: restorePurchases } = useRestorePurchase(userId ?? undefined);
41
+
42
+ // Store pending package for post-auth purchase
43
+ const [pendingPackage, setPendingPackage] = useState<PurchasesPackage | null>(null);
44
+ const wasAnonymousRef = useRef(isAnonymous);
41
45
 
42
46
  const { filteredPackages, computedCreditAmounts } = useMemo(() => {
43
47
  const filtered = filterPackagesByMode(allPackages, mode, packageFilterConfig);
@@ -67,13 +71,50 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = ({
67
71
  }
68
72
  }, [showPaywall, userId, isAnonymous, mode, allPackages.length, filteredPackages.length, isLoading, isFetching, status, error]);
69
73
 
74
+ // Auto-purchase when user authenticates after selecting a package
75
+ useEffect(() => {
76
+ const wasAnonymous = wasAnonymousRef.current;
77
+ wasAnonymousRef.current = isAnonymous;
78
+
79
+ // If user was anonymous, now authenticated, and has pending package
80
+ if (wasAnonymous && !isAnonymous && pendingPackage && userId) {
81
+ if (__DEV__) {
82
+ console.log("[PaywallContainer] User authenticated, auto-purchasing pending package:", pendingPackage.identifier);
83
+ }
84
+
85
+ // Execute the purchase
86
+ (async () => {
87
+ try {
88
+ const result = await purchasePackage(pendingPackage);
89
+ if (result.success) {
90
+ if (__DEV__) {
91
+ console.log("[PaywallContainer] Auto-purchase successful");
92
+ }
93
+ onPurchaseSuccess?.();
94
+ closePaywall();
95
+ }
96
+ } catch (err) {
97
+ const message = err instanceof Error ? err.message : String(err);
98
+ if (__DEV__) {
99
+ console.error("[PaywallContainer] Auto-purchase failed:", message);
100
+ }
101
+ onPurchaseError?.(message);
102
+ } finally {
103
+ setPendingPackage(null);
104
+ }
105
+ })();
106
+ }
107
+ }, [isAnonymous, userId, pendingPackage, purchasePackage, onPurchaseSuccess, onPurchaseError, closePaywall]);
108
+
70
109
  const handlePurchase = useCallback(
71
110
  async (pkg: PurchasesPackage) => {
72
111
  // Auth gating: require authentication for anonymous users
73
112
  if (isAnonymous) {
74
113
  if (__DEV__) {
75
- console.log("[PaywallContainer] Anonymous user, requiring auth before purchase");
114
+ console.log("[PaywallContainer] Anonymous user, storing package and requiring auth:", pkg.identifier);
76
115
  }
116
+ // Store package for auto-purchase after auth
117
+ setPendingPackage(pkg);
77
118
  // Don't close paywall - keep it open so user can purchase after auth
78
119
  onAuthRequired?.();
79
120
  return;
@@ -99,7 +140,7 @@ export const PaywallContainer: React.FC<PaywallContainerProps> = ({
99
140
  onPurchaseError?.(message);
100
141
  }
101
142
  },
102
- [isAnonymous, purchasePackage, closePaywall, onPurchaseSuccess, onPurchaseError, onAuthRequired]
143
+ [isAnonymous, purchasePackage, closePaywall, onPurchaseSuccess, onPurchaseError, onAuthRequired, setPendingPackage]
103
144
  );
104
145
 
105
146
  const handleRestore = useCallback(async () => {
@@ -77,6 +77,9 @@ export const useCredits = ({
77
77
  enabled: enabled && !!userId && isConfigured,
78
78
  staleTime,
79
79
  gcTime,
80
+ refetchOnMount: true, // Refetch when component mounts
81
+ refetchOnWindowFocus: true, // Refetch when app becomes active
82
+ refetchOnReconnect: true, // Refetch when network reconnects
80
83
  });
81
84
 
82
85
  const credits = data ?? null;
@@ -12,5 +12,7 @@ export const SUBSCRIPTION_QUERY_KEYS = {
12
12
  ["subscription", "initialized", userId] as const,
13
13
  } as const;
14
14
 
15
- export const STALE_TIME = 5 * 60 * 1000; // 5 minutes
16
- export const GC_TIME = 30 * 60 * 1000; // 30 minutes
15
+ // No cache - always fetch fresh data for subscription packages
16
+ // This ensures users always see real-time subscription status
17
+ export const STALE_TIME = 0; // Always stale - refetch immediately
18
+ export const GC_TIME = 0; // Don't cache - garbage collect immediately
@@ -38,5 +38,7 @@ export const useSubscriptionPackages = (userId: string | undefined) => {
38
38
  gcTime: GC_TIME,
39
39
  enabled: isConfigured,
40
40
  refetchOnMount: true,
41
+ refetchOnWindowFocus: true, // Refetch when app becomes active
42
+ refetchOnReconnect: true, // Refetch when network reconnects
41
43
  });
42
44
  };