@umituz/react-native-subscription 1.9.0 → 1.10.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
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* useFeatureGate Hook
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Feature gating with TanStack Query for server state.
|
|
5
|
+
* Checks auth and premium status before allowing actions.
|
|
6
6
|
*
|
|
7
7
|
* Flow:
|
|
8
|
-
* 1. NOT authenticated →
|
|
9
|
-
* 2. Authenticated but not premium →
|
|
8
|
+
* 1. NOT authenticated → onShowAuthModal(callback)
|
|
9
|
+
* 2. Authenticated but not premium → onShowPaywall()
|
|
10
10
|
* 3. Authenticated and premium → Execute action
|
|
11
11
|
*
|
|
12
12
|
* @example
|
|
13
13
|
* ```typescript
|
|
14
14
|
* const { requireFeature } = useFeatureGate({
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* onShowAuthModal: (
|
|
15
|
+
* userId: user?.uid,
|
|
16
|
+
* isAuthenticated: !!user,
|
|
17
|
+
* onShowAuthModal: (cb) => authModal.show(cb),
|
|
18
18
|
* onShowPaywall: () => setShowPaywall(true),
|
|
19
|
-
* getIsPremium: () => subscriptionStore.getState().isPremium,
|
|
20
19
|
* });
|
|
21
20
|
*
|
|
21
|
+
* // Gate a premium feature
|
|
22
22
|
* const handleGenerate = () => {
|
|
23
23
|
* requireFeature(() => generateContent());
|
|
24
24
|
* };
|
|
@@ -26,66 +26,70 @@
|
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
28
|
import { useCallback } from "react";
|
|
29
|
+
import { useCredits } from "./useCredits";
|
|
29
30
|
|
|
30
31
|
export interface UseFeatureGateParams {
|
|
31
|
-
/**
|
|
32
|
+
/** User ID for credits check */
|
|
33
|
+
userId: string | undefined;
|
|
34
|
+
/** Whether user is authenticated */
|
|
32
35
|
isAuthenticated: boolean;
|
|
33
|
-
/** Whether user has premium access (for immediate check) */
|
|
34
|
-
isPremium: boolean;
|
|
35
36
|
/** Callback to show auth modal with pending action */
|
|
36
37
|
onShowAuthModal: (pendingCallback: () => void | Promise<void>) => void;
|
|
37
38
|
/** Callback to show paywall */
|
|
38
39
|
onShowPaywall: () => void;
|
|
39
|
-
/** Function to get fresh isPremium status (avoids stale closure after login) */
|
|
40
|
-
getIsPremium: () => boolean;
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
export interface UseFeatureGateResult {
|
|
44
|
-
/** Gate a feature - checks auth first, then premium */
|
|
43
|
+
/** Gate a feature - checks auth first, then premium (credits) */
|
|
45
44
|
requireFeature: (action: () => void | Promise<void>) => void;
|
|
46
45
|
/** Whether user is authenticated */
|
|
47
46
|
isAuthenticated: boolean;
|
|
48
|
-
/** Whether user has premium access */
|
|
47
|
+
/** Whether user has premium access (has credits) */
|
|
49
48
|
isPremium: boolean;
|
|
50
|
-
/** Whether feature access is allowed
|
|
49
|
+
/** Whether feature access is allowed */
|
|
51
50
|
canAccess: boolean;
|
|
51
|
+
/** Loading state */
|
|
52
|
+
isLoading: boolean;
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export function useFeatureGate(
|
|
55
56
|
params: UseFeatureGateParams
|
|
56
57
|
): UseFeatureGateResult {
|
|
57
|
-
const {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
58
|
+
const { userId, isAuthenticated, onShowAuthModal, onShowPaywall } = params;
|
|
59
|
+
|
|
60
|
+
// Use TanStack Query to get credits (server state)
|
|
61
|
+
const { credits, isLoading } = useCredits({
|
|
62
|
+
userId,
|
|
63
|
+
enabled: isAuthenticated && !!userId,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
// User is premium if they have credits
|
|
67
|
+
const isPremium = credits !== null;
|
|
64
68
|
|
|
65
69
|
const requireFeature = useCallback(
|
|
66
70
|
(action: () => void | Promise<void>) => {
|
|
67
|
-
// Step 1: Check
|
|
71
|
+
// Step 1: Check authentication
|
|
68
72
|
if (!isAuthenticated) {
|
|
69
|
-
// After
|
|
73
|
+
// After auth, re-check premium before executing
|
|
70
74
|
onShowAuthModal(() => {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
onShowPaywall();
|
|
76
|
-
}
|
|
75
|
+
// This callback runs after successful auth
|
|
76
|
+
// The component will re-render with new auth state
|
|
77
|
+
// and user can try the action again
|
|
78
|
+
action();
|
|
77
79
|
});
|
|
78
80
|
return;
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
// Step 2: Check premium (
|
|
82
|
-
if (isPremium) {
|
|
83
|
-
action();
|
|
84
|
-
} else {
|
|
83
|
+
// Step 2: Check premium (has credits from TanStack Query)
|
|
84
|
+
if (!isPremium) {
|
|
85
85
|
onShowPaywall();
|
|
86
|
+
return;
|
|
86
87
|
}
|
|
88
|
+
|
|
89
|
+
// Step 3: User is authenticated and premium - execute action
|
|
90
|
+
action();
|
|
87
91
|
},
|
|
88
|
-
[isAuthenticated, isPremium, onShowAuthModal, onShowPaywall
|
|
92
|
+
[isAuthenticated, isPremium, onShowAuthModal, onShowPaywall]
|
|
89
93
|
);
|
|
90
94
|
|
|
91
95
|
return {
|
|
@@ -93,5 +97,6 @@ export function useFeatureGate(
|
|
|
93
97
|
isAuthenticated,
|
|
94
98
|
isPremium,
|
|
95
99
|
canAccess: isAuthenticated && isPremium,
|
|
100
|
+
isLoading,
|
|
96
101
|
};
|
|
97
102
|
}
|