@umituz/react-native-subscription 2.13.11 → 2.13.12

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.13.11",
3
+ "version": "2.13.12",
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",
@@ -2,12 +2,12 @@
2
2
  * useFeatureGate Hook
3
3
  *
4
4
  * Feature gating with TanStack Query for server state.
5
- * Checks auth and premium status before allowing actions.
5
+ * Checks auth, premium status, AND credit balance before allowing actions.
6
6
  *
7
7
  * Flow:
8
8
  * 1. NOT authenticated → onShowAuthModal(callback)
9
- * 2. Authenticated but not premium → onShowPaywall()
10
- * 3. Authenticated and premium → Execute action
9
+ * 2. Authenticated but no credits → onShowPaywall()
10
+ * 3. Authenticated with credits → Execute action
11
11
  *
12
12
  * @example
13
13
  * ```typescript
@@ -16,6 +16,7 @@
16
16
  * isAuthenticated: !!user,
17
17
  * onShowAuthModal: (cb) => authModal.show(cb),
18
18
  * onShowPaywall: () => setShowPaywall(true),
19
+ * creditType: 'image', // or 'text'
19
20
  * });
20
21
  *
21
22
  * // Gate a premium feature
@@ -27,6 +28,7 @@
27
28
 
28
29
  import { useCallback } from "react";
29
30
  import { useCredits } from "./useCredits";
31
+ import type { CreditType } from "../../domain/entities/Credits";
30
32
 
31
33
  declare const __DEV__: boolean;
32
34
 
@@ -39,67 +41,107 @@ export interface UseFeatureGateParams {
39
41
  onShowAuthModal: (pendingCallback: () => void | Promise<void>) => void;
40
42
  /** Callback to show paywall */
41
43
  onShowPaywall: () => void;
44
+ /** Credit type to check (default: 'image') */
45
+ creditType?: CreditType;
42
46
  }
43
47
 
44
48
  export interface UseFeatureGateResult {
45
- /** Gate a feature - checks auth first, then premium (credits) */
49
+ /** Gate a feature - checks auth first, then credits balance */
46
50
  requireFeature: (action: () => void | Promise<void>) => void;
47
51
  /** Whether user is authenticated */
48
52
  isAuthenticated: boolean;
49
- /** Whether user has premium access (has credits) */
50
- isPremium: boolean;
53
+ /** Whether user has credits remaining */
54
+ hasCredits: boolean;
51
55
  /** Whether feature access is allowed */
52
56
  canAccess: boolean;
53
57
  /** Loading state */
54
58
  isLoading: boolean;
59
+ /** Current credit balance for the specified type */
60
+ creditBalance: number;
55
61
  }
56
62
 
57
63
  export function useFeatureGate(
58
64
  params: UseFeatureGateParams
59
65
  ): UseFeatureGateResult {
60
- const { userId, isAuthenticated, onShowAuthModal, onShowPaywall } = params;
66
+ const {
67
+ userId,
68
+ isAuthenticated,
69
+ onShowAuthModal,
70
+ onShowPaywall,
71
+ creditType = "image",
72
+ } = params;
61
73
 
62
74
  // Use TanStack Query to get credits (server state)
63
- const { credits, isLoading } = useCredits({
75
+ const { credits, isLoading, hasImageCredits, hasTextCredits } = useCredits({
64
76
  userId,
65
77
  enabled: isAuthenticated && !!userId,
66
78
  });
67
79
 
68
- // User is premium if they have credits
69
- // NOTE: This assumes credits system = premium subscription
70
- // If your app uses CustomerInfo for premium status, use useCustomerInfo() instead
71
- const isPremium = credits !== null;
80
+ // Check actual credit balance, not just existence
81
+ const hasCredits = creditType === "image" ? hasImageCredits : hasTextCredits;
82
+ const creditBalance =
83
+ creditType === "image"
84
+ ? credits?.imageCredits ?? 0
85
+ : credits?.textCredits ?? 0;
72
86
 
73
87
  const requireFeature = useCallback(
74
88
  (action: () => void | Promise<void>) => {
89
+ if (__DEV__) {
90
+ console.log("[useFeatureGate] requireFeature called", {
91
+ isAuthenticated,
92
+ hasCredits,
93
+ creditBalance,
94
+ creditType,
95
+ });
96
+ }
97
+
75
98
  // Step 1: Check authentication
76
99
  if (!isAuthenticated) {
100
+ if (__DEV__) {
101
+ console.log("[useFeatureGate] Not authenticated, showing auth modal");
102
+ }
77
103
  onShowAuthModal(() => {
78
104
  // We NO LONGER call action() blindly here.
79
105
  // The component will re-render with the new auth state,
80
106
  // and the user should be allowed to try the action again.
81
- // This avoids executing actions before credits are loaded or verified.
82
107
  });
83
108
  return;
84
109
  }
85
110
 
86
- // Step 2: Check premium (has credits from TanStack Query)
87
- if (!isPremium) {
111
+ // Step 2: Check credit balance (not just existence)
112
+ if (!hasCredits) {
113
+ if (__DEV__) {
114
+ console.log("[useFeatureGate] No credits, showing paywall", {
115
+ creditBalance,
116
+ creditType,
117
+ });
118
+ }
88
119
  onShowPaywall();
89
120
  return;
90
121
  }
91
122
 
92
- // Step 3: User is authenticated and premium - execute action
123
+ // Step 3: User is authenticated with credits - execute action
124
+ if (__DEV__) {
125
+ console.log("[useFeatureGate] Access granted, executing action");
126
+ }
93
127
  action();
94
128
  },
95
- [isAuthenticated, isPremium, onShowAuthModal, onShowPaywall]
129
+ [
130
+ isAuthenticated,
131
+ hasCredits,
132
+ creditBalance,
133
+ creditType,
134
+ onShowAuthModal,
135
+ onShowPaywall,
136
+ ]
96
137
  );
97
138
 
98
139
  return {
99
140
  requireFeature,
100
141
  isAuthenticated,
101
- isPremium,
102
- canAccess: isAuthenticated && isPremium,
142
+ hasCredits,
143
+ canAccess: isAuthenticated && hasCredits,
103
144
  isLoading,
145
+ creditBalance,
104
146
  };
105
147
  }