@umituz/react-native-subscription 2.26.14 → 2.26.16
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/PaywallModal.tsx +36 -13
- package/src/domains/paywall/components/PlanCard.tsx +16 -3
- package/src/domains/paywall/entities/types.ts +4 -0
- package/src/domains/paywall/hooks/usePaywallTranslations.ts +8 -0
- package/src/presentation/hooks/index.ts +0 -13
- package/src/presentation/hooks/useFeatureGate.ts +12 -33
- package/src/revenuecat/domain/types/RevenueCatTypes.ts +32 -0
- package/src/revenuecat/index.ts +1 -0
- package/src/revenuecat/presentation/hooks/useRevenueCatTrialEligibility.ts +179 -0
- package/src/presentation/hooks/useAuthAwarePurchase.md +0 -92
- package/src/presentation/hooks/useAuthGate.md +0 -89
- package/src/presentation/hooks/useAuthGate.ts +0 -65
- package/src/presentation/hooks/useCreditChecker.md +0 -102
- package/src/presentation/hooks/useCreditChecker.ts +0 -41
- package/src/presentation/hooks/useCreditsGate.md +0 -94
- package/src/presentation/hooks/useCreditsGate.ts +0 -67
- package/src/presentation/hooks/useDevTestCallbacks.md +0 -91
- package/src/presentation/hooks/useDevTestCallbacks.ts +0 -142
- package/src/presentation/hooks/useInitializeCredits.md +0 -92
- package/src/presentation/hooks/useInitializeCredits.ts +0 -57
- package/src/presentation/hooks/usePremiumGate.md +0 -88
- package/src/presentation/hooks/usePremiumGate.ts +0 -116
- package/src/presentation/hooks/usePremiumWithCredits.md +0 -92
- package/src/presentation/hooks/usePremiumWithCredits.ts +0 -48
- package/src/presentation/hooks/useSubscription.md +0 -94
- package/src/presentation/hooks/useSubscription.ts +0 -119
- package/src/presentation/hooks/useSubscriptionDetails.md +0 -93
- package/src/presentation/hooks/useSubscriptionDetails.ts +0 -85
- package/src/presentation/hooks/useSubscriptionGate.md +0 -84
- package/src/presentation/hooks/useSubscriptionGate.ts +0 -67
- package/src/presentation/hooks/useSubscriptionStatus.md +0 -94
- package/src/presentation/hooks/useTrialEligibility.ts +0 -66
- package/src/presentation/hooks/useUserTier.md +0 -91
- package/src/presentation/hooks/useUserTier.ts +0 -78
- package/src/presentation/hooks/useUserTierWithRepository.md +0 -92
- package/src/presentation/hooks/useUserTierWithRepository.ts +0 -151
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# useInitializeCredits Hook
|
|
2
|
-
|
|
3
|
-
TanStack Query mutation hook for initializing credits after purchase.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/useInitializeCredits.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Credit Initialization Flow
|
|
16
|
-
|
|
17
|
-
1. **User Validation**: Verify user is authenticated before initialization
|
|
18
|
-
2. **Repository Call**: Call credits repository to initialize credits
|
|
19
|
-
3. **Duplicate Protection**: Repository prevents duplicate initialization with same purchase ID
|
|
20
|
-
4. **Loading State**: Track initialization progress with isInitializing flag
|
|
21
|
-
5. **Error Handling**: Handle and report initialization failures
|
|
22
|
-
6. **Success Tracking**: Return success boolean for caller to handle
|
|
23
|
-
|
|
24
|
-
### Integration Points
|
|
25
|
-
|
|
26
|
-
- **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
|
|
27
|
-
- **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
|
|
28
|
-
- **TanStack Query**: For mutation and optimistic updates
|
|
29
|
-
- **Purchase Flow**: Called after successful subscription purchase
|
|
30
|
-
|
|
31
|
-
## Restrictions
|
|
32
|
-
|
|
33
|
-
### REQUIRED
|
|
34
|
-
|
|
35
|
-
- **User ID**: MUST provide valid userId parameter
|
|
36
|
-
- **Authentication**: User MUST be authenticated
|
|
37
|
-
- **Error Handling**: MUST handle initialization failures
|
|
38
|
-
- **Loading State**: MUST show loading indicator during initialization
|
|
39
|
-
|
|
40
|
-
### PROHIBITED
|
|
41
|
-
|
|
42
|
-
- **NEVER** initialize credits without valid userId
|
|
43
|
-
- **NEVER** call for unauthenticated users
|
|
44
|
-
- **DO NOT** assume successful initialization (check return value)
|
|
45
|
-
- **DO NOT** call excessively (repository handles duplicates)
|
|
46
|
-
|
|
47
|
-
### CRITICAL SAFETY
|
|
48
|
-
|
|
49
|
-
- **ALWAYS** validate userId before initialization
|
|
50
|
-
- **MUST** handle errors gracefully
|
|
51
|
-
- **ALWAYS** check return value
|
|
52
|
-
- **NEVER** rely on side effects without checking success
|
|
53
|
-
|
|
54
|
-
## AI Agent Guidelines
|
|
55
|
-
|
|
56
|
-
### When Implementing Credit Initialization
|
|
57
|
-
|
|
58
|
-
1. **Always** validate userId before calling initializeCredits
|
|
59
|
-
2. **Always** handle loading state
|
|
60
|
-
3. **Always** check return value
|
|
61
|
-
4. **Always** provide purchaseId and productId when available
|
|
62
|
-
5. **Never** initialize credits for unauthenticated users
|
|
63
|
-
|
|
64
|
-
### Integration Checklist
|
|
65
|
-
|
|
66
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
67
|
-
- [ ] Validate userId is not undefined
|
|
68
|
-
- [ ] Handle isInitializing state
|
|
69
|
-
- [ ] Check return value from initializeCredits
|
|
70
|
-
- [ ] Provide purchaseId when available
|
|
71
|
-
- [ ] Provide productId when available
|
|
72
|
-
- [ ] Test with premium user (no existing credits)
|
|
73
|
-
- [ ] Test with premium user (existing credits)
|
|
74
|
-
- [ ] Test duplicate protection
|
|
75
|
-
- [ ] Test error scenarios
|
|
76
|
-
|
|
77
|
-
### Common Patterns
|
|
78
|
-
|
|
79
|
-
1. **Post-Purchase Init**: Initialize after successful purchase
|
|
80
|
-
2. **Auto-Init for Premium**: Automatically initialize for premium users without credits
|
|
81
|
-
3. **Product-Specific Allocation**: Different products provide different credit amounts
|
|
82
|
-
4. **Retry Logic**: Implement retry mechanism on failure
|
|
83
|
-
5. **Admin Init**: Manual initialization for admin users
|
|
84
|
-
|
|
85
|
-
## Related Documentation
|
|
86
|
-
|
|
87
|
-
- **useCredits**: For accessing credits balance
|
|
88
|
-
- **useDeductCredit**: For deducting credits
|
|
89
|
-
- **usePremiumWithCredits**: For premium + credits integration
|
|
90
|
-
- **useDevTestCallbacks**: For testing credit initialization
|
|
91
|
-
- **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
|
|
92
|
-
- **Wallet Domain**: `src/domains/wallet/README.md`
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useInitializeCredits Hook
|
|
3
|
-
* TanStack Query mutation hook for initializing credits after purchase.
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useCallback } from "react";
|
|
7
|
-
import { useMutation, useQueryClient } from "@umituz/react-native-design-system";
|
|
8
|
-
import { getCreditsRepository } from "../../infrastructure/repositories/CreditsRepositoryProvider";
|
|
9
|
-
import { creditsQueryKeys } from "./useCredits";
|
|
10
|
-
|
|
11
|
-
declare const __DEV__: boolean;
|
|
12
|
-
|
|
13
|
-
export interface UseInitializeCreditsParams {
|
|
14
|
-
userId: string | undefined;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface InitializeCreditsOptions {
|
|
18
|
-
purchaseId?: string;
|
|
19
|
-
productId?: string;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export interface UseInitializeCreditsResult {
|
|
23
|
-
initializeCredits: (options?: InitializeCreditsOptions) => Promise<boolean>;
|
|
24
|
-
isInitializing: boolean;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export const useInitializeCredits = ({
|
|
28
|
-
userId,
|
|
29
|
-
}: UseInitializeCreditsParams): UseInitializeCreditsResult => {
|
|
30
|
-
const repository = getCreditsRepository();
|
|
31
|
-
const queryClient = useQueryClient();
|
|
32
|
-
|
|
33
|
-
const mutation = useMutation({
|
|
34
|
-
mutationFn: async (options?: InitializeCreditsOptions) => {
|
|
35
|
-
if (!userId) throw new Error("User not authenticated");
|
|
36
|
-
if (__DEV__) console.log("[useInitializeCredits] Initializing:", { userId, ...options });
|
|
37
|
-
return repository.initializeCredits(userId, options?.purchaseId, options?.productId);
|
|
38
|
-
},
|
|
39
|
-
onSuccess: (result) => {
|
|
40
|
-
if (userId && result.success && result.data) {
|
|
41
|
-
if (__DEV__) console.log("[useInitializeCredits] Success:", result.data);
|
|
42
|
-
queryClient.setQueryData(creditsQueryKeys.user(userId), result.data);
|
|
43
|
-
queryClient.invalidateQueries({ queryKey: creditsQueryKeys.user(userId) });
|
|
44
|
-
}
|
|
45
|
-
},
|
|
46
|
-
onError: (error) => { if (__DEV__) console.error("[useInitializeCredits] Error:", error); },
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
const initializeCredits = useCallback(async (opts?: InitializeCreditsOptions): Promise<boolean> => {
|
|
50
|
-
try {
|
|
51
|
-
const res = await mutation.mutateAsync(opts);
|
|
52
|
-
return res.success;
|
|
53
|
-
} catch { return false; }
|
|
54
|
-
}, [mutation]);
|
|
55
|
-
|
|
56
|
-
return { initializeCredits, isInitializing: mutation.isPending };
|
|
57
|
-
};
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# usePremiumGate Hook
|
|
2
|
-
|
|
3
|
-
Feature gating hook for premium-only features with optional authentication.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/usePremiumGate.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Premium Gating Flow
|
|
16
|
-
|
|
17
|
-
1. **Premium Check**: Verify if user has premium access
|
|
18
|
-
2. **Auth Check**: Optionally verify authentication status
|
|
19
|
-
3. **Gate Functions**: Provide requirePremium, requireAuth, requirePremiumWithAuth
|
|
20
|
-
4. **Access Control**: Simple booleans for conditional rendering (canAccess, canAccessWithAuth)
|
|
21
|
-
5. **Callback Triggers**: Execute appropriate callback when requirements not met
|
|
22
|
-
|
|
23
|
-
### Integration Points
|
|
24
|
-
|
|
25
|
-
- **usePremium**: For premium status check
|
|
26
|
-
- **useAuth**: For authentication status
|
|
27
|
-
- **Paywall Domain**: For premium upgrade flow
|
|
28
|
-
- **Auth UI**: For authentication flow
|
|
29
|
-
|
|
30
|
-
## Restrictions
|
|
31
|
-
|
|
32
|
-
### REQUIRED
|
|
33
|
-
|
|
34
|
-
- **Premium Status**: MUST provide isPremium parameter
|
|
35
|
-
- **Callback**: MUST implement onPremiumRequired callback
|
|
36
|
-
- **Access Check**: MUST verify canAccess before showing premium content
|
|
37
|
-
|
|
38
|
-
### PROHIBITED
|
|
39
|
-
|
|
40
|
-
- **NEVER** show premium content without checking isPremium
|
|
41
|
-
- **NEVER** use for security decisions without server validation
|
|
42
|
-
- **DO NOT** assume premium status (always verify)
|
|
43
|
-
|
|
44
|
-
### CRITICAL SAFETY
|
|
45
|
-
|
|
46
|
-
- **ALWAYS** verify canAccess before showing premium features
|
|
47
|
-
- **NEVER** trust client-side state for security
|
|
48
|
-
- **MUST** implement proper upgrade flow
|
|
49
|
-
- **ALWAYS** handle authentication when required
|
|
50
|
-
|
|
51
|
-
## AI Agent Guidelines
|
|
52
|
-
|
|
53
|
-
### When Implementing Premium Gates
|
|
54
|
-
|
|
55
|
-
1. **Always** check canAccess before showing premium content
|
|
56
|
-
2. **Always** provide clear upgrade path in callback
|
|
57
|
-
3. **Always** use requirePremium for action gating
|
|
58
|
-
4. **Always** handle authentication when using requirePremiumWithAuth
|
|
59
|
-
5. **Never** bypass premium checks
|
|
60
|
-
|
|
61
|
-
### Integration Checklist
|
|
62
|
-
|
|
63
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
64
|
-
- [ ] Provide isPremium from usePremium
|
|
65
|
-
- [ ] Implement onPremiumRequired callback
|
|
66
|
-
- [ ] Optionally provide auth status and callback
|
|
67
|
-
- [ ] Use requirePremium for action gating
|
|
68
|
-
- [ ] Check canAccess for conditional rendering
|
|
69
|
-
- [ ] Test with premium user
|
|
70
|
-
- [ ] Test with non-premium user
|
|
71
|
-
- [ ] Test with authenticated user
|
|
72
|
-
- [ ] Test with unauthenticated user
|
|
73
|
-
|
|
74
|
-
### Common Patterns
|
|
75
|
-
|
|
76
|
-
1. **Premium Only**: Gate features behind premium only
|
|
77
|
-
2. **Auth + Premium**: Require both authentication and premium
|
|
78
|
-
3. **Conditional Rendering**: Check canAccess for UI
|
|
79
|
-
4. **Button States**: Disable buttons when not premium
|
|
80
|
-
5. **Upgrade Prompts**: Show in callback when not premium
|
|
81
|
-
|
|
82
|
-
## Related Documentation
|
|
83
|
-
|
|
84
|
-
- **usePremium**: Premium status check
|
|
85
|
-
- **useAuthGate**: Auth + subscription gating
|
|
86
|
-
- **useSubscriptionGate**: Subscription-only gating
|
|
87
|
-
- **useFeatureGate**: Unified feature gating
|
|
88
|
-
- **Paywall Domain**: `src/domains/paywall/README.md`
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* usePremiumGate Hook
|
|
3
|
-
*
|
|
4
|
-
* Feature gating hook for premium-only features
|
|
5
|
-
* Provides a simple way to gate features behind premium subscription
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```typescript
|
|
9
|
-
* const { requirePremium, isPremium } = usePremiumGate({
|
|
10
|
-
* isPremium: subscriptionStore.isPremium,
|
|
11
|
-
* onPremiumRequired: () => navigation.navigate('Paywall'),
|
|
12
|
-
* });
|
|
13
|
-
*
|
|
14
|
-
* const handleGenerate = () => {
|
|
15
|
-
* requirePremium(() => {
|
|
16
|
-
* // This only runs if user is premium
|
|
17
|
-
* generateContent();
|
|
18
|
-
* });
|
|
19
|
-
* };
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { useCallback, useMemo } from "react";
|
|
24
|
-
|
|
25
|
-
export interface UsePremiumGateParams {
|
|
26
|
-
/** Whether user has premium access */
|
|
27
|
-
isPremium: boolean;
|
|
28
|
-
/** Callback when premium is required but user is not premium */
|
|
29
|
-
onPremiumRequired: () => void;
|
|
30
|
-
/** Optional: Whether user is authenticated */
|
|
31
|
-
isAuthenticated?: boolean;
|
|
32
|
-
/** Optional: Callback when auth is required but user is not authenticated */
|
|
33
|
-
onAuthRequired?: () => void;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export interface UsePremiumGateResult {
|
|
37
|
-
/** Whether user has premium access */
|
|
38
|
-
isPremium: boolean;
|
|
39
|
-
/** Whether user is authenticated */
|
|
40
|
-
isAuthenticated: boolean;
|
|
41
|
-
/** Gate a feature behind premium - executes action if premium, else calls onPremiumRequired */
|
|
42
|
-
requirePremium: (action: () => void) => void;
|
|
43
|
-
/** Gate a feature behind auth - executes action if authenticated, else calls onAuthRequired */
|
|
44
|
-
requireAuth: (action: () => void) => void;
|
|
45
|
-
/** Gate a feature behind both auth and premium */
|
|
46
|
-
requirePremiumWithAuth: (action: () => void) => void;
|
|
47
|
-
/** Check if feature is accessible (premium check only) */
|
|
48
|
-
canAccess: boolean;
|
|
49
|
-
/** Check if feature is accessible (auth + premium) */
|
|
50
|
-
canAccessWithAuth: boolean;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export function usePremiumGate(
|
|
54
|
-
params: UsePremiumGateParams
|
|
55
|
-
): UsePremiumGateResult {
|
|
56
|
-
const {
|
|
57
|
-
isPremium,
|
|
58
|
-
onPremiumRequired,
|
|
59
|
-
isAuthenticated = true,
|
|
60
|
-
onAuthRequired,
|
|
61
|
-
} = params;
|
|
62
|
-
|
|
63
|
-
const requirePremium = useCallback(
|
|
64
|
-
(action: () => void) => {
|
|
65
|
-
if (isPremium) {
|
|
66
|
-
action();
|
|
67
|
-
} else {
|
|
68
|
-
onPremiumRequired();
|
|
69
|
-
}
|
|
70
|
-
},
|
|
71
|
-
[isPremium, onPremiumRequired]
|
|
72
|
-
);
|
|
73
|
-
|
|
74
|
-
const requireAuth = useCallback(
|
|
75
|
-
(action: () => void) => {
|
|
76
|
-
if (isAuthenticated) {
|
|
77
|
-
action();
|
|
78
|
-
} else {
|
|
79
|
-
onAuthRequired?.();
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
[isAuthenticated, onAuthRequired]
|
|
83
|
-
);
|
|
84
|
-
|
|
85
|
-
const requirePremiumWithAuth = useCallback(
|
|
86
|
-
(action: () => void) => {
|
|
87
|
-
if (!isAuthenticated) {
|
|
88
|
-
onAuthRequired?.();
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
if (!isPremium) {
|
|
92
|
-
onPremiumRequired();
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
action();
|
|
96
|
-
},
|
|
97
|
-
[isAuthenticated, isPremium, onAuthRequired, onPremiumRequired]
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
const canAccess = useMemo(() => isPremium, [isPremium]);
|
|
101
|
-
|
|
102
|
-
const canAccessWithAuth = useMemo(
|
|
103
|
-
() => isAuthenticated && isPremium,
|
|
104
|
-
[isAuthenticated, isPremium]
|
|
105
|
-
);
|
|
106
|
-
|
|
107
|
-
return {
|
|
108
|
-
isPremium,
|
|
109
|
-
isAuthenticated,
|
|
110
|
-
requirePremium,
|
|
111
|
-
requireAuth,
|
|
112
|
-
requirePremiumWithAuth,
|
|
113
|
-
canAccess,
|
|
114
|
-
canAccessWithAuth,
|
|
115
|
-
};
|
|
116
|
-
}
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
# usePremiumWithCredits Hook
|
|
2
|
-
|
|
3
|
-
Combined hook for premium subscription with credits system integration.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/usePremiumWithCredits.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Premium + Credits Integration
|
|
16
|
-
|
|
17
|
-
1. **Credits Access**: Provide all credits data from useCredits hook
|
|
18
|
-
2. **Auto-Initialization**: Automatically initialize credits when user becomes premium
|
|
19
|
-
3. **Premium Check**: Monitor isPremium status to trigger initialization
|
|
20
|
-
4. **Duplicate Prevention**: Skip initialization if credits already exist
|
|
21
|
-
5. **Loading Management**: Handle loading state during initialization
|
|
22
|
-
6. **Error Handling**: Handle initialization failures gracefully
|
|
23
|
-
|
|
24
|
-
### Integration Points
|
|
25
|
-
|
|
26
|
-
- **useCredits**: For credits balance and transactions
|
|
27
|
-
- **usePremium**: For premium status check
|
|
28
|
-
- **useInitializeCredits**: For credit initialization
|
|
29
|
-
- **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
|
|
30
|
-
|
|
31
|
-
## Restrictions
|
|
32
|
-
|
|
33
|
-
### REQUIRED
|
|
34
|
-
|
|
35
|
-
- **User ID**: MUST provide valid userId parameter
|
|
36
|
-
- **Premium Status**: MUST provide isPremium parameter
|
|
37
|
-
- **Loading State**: MUST handle loading state
|
|
38
|
-
- **Error Handling**: MUST handle initialization errors
|
|
39
|
-
|
|
40
|
-
### PROHIBITED
|
|
41
|
-
|
|
42
|
-
- **NEVER** call without valid userId
|
|
43
|
-
- **NEVER** call without isPremium parameter
|
|
44
|
-
- **DO NOT** manually manage credits state (use hook values)
|
|
45
|
-
- **DO NOT** call ensureCreditsInitialized excessively
|
|
46
|
-
|
|
47
|
-
### CRITICAL SAFETY
|
|
48
|
-
|
|
49
|
-
- **ALWAYS** validate userId before use
|
|
50
|
-
- **MUST** handle loading state during initialization
|
|
51
|
-
- **ALWAYS** check isPremium before showing premium features
|
|
52
|
-
- **NEVER** trust client-side state for security
|
|
53
|
-
|
|
54
|
-
## AI Agent Guidelines
|
|
55
|
-
|
|
56
|
-
### When Implementing Premium + Credits
|
|
57
|
-
|
|
58
|
-
1. **Always** provide valid userId
|
|
59
|
-
2. **Always** provide isPremium status
|
|
60
|
-
3. **Always** handle loading state
|
|
61
|
-
4. **Always** call ensureCreditsInitialized for premium users
|
|
62
|
-
5. **Never** manually initialize credits without checking isPremium
|
|
63
|
-
|
|
64
|
-
### Integration Checklist
|
|
65
|
-
|
|
66
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
67
|
-
- [ ] Provide valid userId
|
|
68
|
-
- [ ] Provide isPremium from usePremium
|
|
69
|
-
- [ ] Handle loading state
|
|
70
|
-
- [ ] Call ensureCreditsInitialized when isPremium is true
|
|
71
|
-
- [ ] Test with premium user (no credits)
|
|
72
|
-
- [ ] Test with premium user (has credits)
|
|
73
|
-
- [ ] Test with free user
|
|
74
|
-
- [ ] Test subscription upgrade flow
|
|
75
|
-
- [ ] Test error scenarios
|
|
76
|
-
|
|
77
|
-
### Common Patterns
|
|
78
|
-
|
|
79
|
-
1. **Auto-Initialization**: Automatically initialize credits for premium users
|
|
80
|
-
2. **Subscription Change Detection**: Detect when user subscribes
|
|
81
|
-
3. **Premium Benefits Display**: Show credits along with premium status
|
|
82
|
-
4. **Subscription Monitor**: Refresh status periodically
|
|
83
|
-
5. **Manual Init**: Provide button for manual initialization
|
|
84
|
-
|
|
85
|
-
## Related Documentation
|
|
86
|
-
|
|
87
|
-
- **useCredits**: Credits management
|
|
88
|
-
- **useInitializeCredits**: Manual credit initialization
|
|
89
|
-
- **usePremium**: Premium status
|
|
90
|
-
- **useDeductCredit**: Credit deduction
|
|
91
|
-
- **Credits System**: `src/domains/wallet/README.md`
|
|
92
|
-
- **Premium Integration**: `src/docs/PREMIUM_INTEGRATION.md`
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* usePremiumWithCredits Hook
|
|
3
|
-
*
|
|
4
|
-
* Combined hook for premium subscription with credits system.
|
|
5
|
-
* Ensures premium users always have credits initialized.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { useEffect, useCallback } from "react";
|
|
9
|
-
import { useCredits, type UseCreditsResult } from "./useCredits";
|
|
10
|
-
import { useInitializeCredits } from "./useInitializeCredits";
|
|
11
|
-
|
|
12
|
-
export interface UsePremiumWithCreditsParams {
|
|
13
|
-
userId: string | undefined;
|
|
14
|
-
isPremium: boolean;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export interface UsePremiumWithCreditsResult extends UseCreditsResult {
|
|
18
|
-
ensureCreditsInitialized: () => Promise<void>;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export const usePremiumWithCredits = ({
|
|
22
|
-
userId,
|
|
23
|
-
isPremium,
|
|
24
|
-
}: UsePremiumWithCreditsParams): UsePremiumWithCreditsResult => {
|
|
25
|
-
const creditsResult = useCredits({ userId });
|
|
26
|
-
const { initializeCredits, isInitializing } = useInitializeCredits({
|
|
27
|
-
userId,
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
const ensureCreditsInitialized = useCallback(async () => {
|
|
31
|
-
if (!userId || !isPremium) return;
|
|
32
|
-
if (creditsResult.credits) return;
|
|
33
|
-
if (isInitializing) return;
|
|
34
|
-
|
|
35
|
-
await initializeCredits();
|
|
36
|
-
}, [userId, isPremium, creditsResult.credits, isInitializing, initializeCredits]);
|
|
37
|
-
|
|
38
|
-
useEffect(() => {
|
|
39
|
-
if (isPremium && userId && !creditsResult.credits && !creditsResult.isLoading) {
|
|
40
|
-
ensureCreditsInitialized();
|
|
41
|
-
}
|
|
42
|
-
}, [isPremium, userId, creditsResult.credits, creditsResult.isLoading, ensureCreditsInitialized]);
|
|
43
|
-
|
|
44
|
-
return {
|
|
45
|
-
...creditsResult,
|
|
46
|
-
ensureCreditsInitialized,
|
|
47
|
-
};
|
|
48
|
-
};
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# useSubscription Hook
|
|
2
|
-
|
|
3
|
-
Core hook for subscription status management and operations.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/useSubscription.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Subscription Management Flow
|
|
16
|
-
|
|
17
|
-
1. **Status Retrieval**: Fetch current subscription status from repository
|
|
18
|
-
2. **State Caching**: Cache status for 5 minutes using TanStack Query
|
|
19
|
-
3. **Real-time Updates**: Auto-refresh when user auth state changes
|
|
20
|
-
4. **Manual Operations**: Provide functions for manual activation/deactivation
|
|
21
|
-
5. **Loading States**: Handle loading and error states properly
|
|
22
|
-
6. **Refresh Mechanisms**: Support both load and refresh operations
|
|
23
|
-
|
|
24
|
-
### Integration Points
|
|
25
|
-
|
|
26
|
-
- **Subscription Repository**: `src/infrastructure/repositories/SubscriptionRepository.ts`
|
|
27
|
-
- **TanStack Query**: For caching and background updates
|
|
28
|
-
- **Auth Context**: Sync with user authentication state
|
|
29
|
-
- **RevenueCat**: For subscription data source
|
|
30
|
-
|
|
31
|
-
## Restrictions
|
|
32
|
-
|
|
33
|
-
### REQUIRED
|
|
34
|
-
|
|
35
|
-
- **User ID**: MUST provide valid userId for operations
|
|
36
|
-
- **Loading State**: MUST handle loading state in UI
|
|
37
|
-
- **Error Handling**: MUST handle error state
|
|
38
|
-
- **Status Check**: MUST verify isPremium before showing premium features
|
|
39
|
-
|
|
40
|
-
### PROHIBITED
|
|
41
|
-
|
|
42
|
-
- **NEVER** assume instant data availability (always check loading state)
|
|
43
|
-
- **NEVER** use for security decisions without server validation
|
|
44
|
-
- **DO NOT** call loadStatus/refreshStatus without userId
|
|
45
|
-
- **DO NOT** activate/deactivate subscriptions without proper validation
|
|
46
|
-
|
|
47
|
-
### CRITICAL SAFETY
|
|
48
|
-
|
|
49
|
-
- **ALWAYS** check loading state before accessing status
|
|
50
|
-
- **NEVER** trust client-side state for security enforcement
|
|
51
|
-
- **MUST** validate userId before all operations
|
|
52
|
-
- **ALWAYS** handle errors gracefully
|
|
53
|
-
|
|
54
|
-
## AI Agent Guidelines
|
|
55
|
-
|
|
56
|
-
### When Implementing Subscription Features
|
|
57
|
-
|
|
58
|
-
1. **Always** check loading state before rendering subscription data
|
|
59
|
-
2. **Always** handle error state
|
|
60
|
-
3. **Always** verify isPremium before showing premium features
|
|
61
|
-
4. **Always** validate userId before operations
|
|
62
|
-
5. **Never** use for security decisions without server validation
|
|
63
|
-
|
|
64
|
-
### Integration Checklist
|
|
65
|
-
|
|
66
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
67
|
-
- [ ] Handle loading state
|
|
68
|
-
- [ ] Handle error state
|
|
69
|
-
- [ ] Check isPremium before rendering premium content
|
|
70
|
-
- [ ] Validate userId before operations
|
|
71
|
-
- [ ] Implement refresh mechanism
|
|
72
|
-
- [ ] Test with premium user
|
|
73
|
-
- [ ] Test with free user
|
|
74
|
-
- [ ] Test with guest user
|
|
75
|
-
- [ ] Test offline scenario
|
|
76
|
-
|
|
77
|
-
### Common Patterns
|
|
78
|
-
|
|
79
|
-
1. **Status Display**: Show current subscription status
|
|
80
|
-
2. **Conditional Rendering**: Show/hide features based on isPremium
|
|
81
|
-
3. **Manual Refresh**: Provide refresh button for users
|
|
82
|
-
4. **Auto-refresh**: Refresh on screen focus or app foreground
|
|
83
|
-
5. **Status Polling**: Periodic refresh for real-time updates
|
|
84
|
-
6. **Purchase Completion**: Refresh after successful purchase
|
|
85
|
-
7. **Error Recovery**: Provide retry mechanism on failure
|
|
86
|
-
|
|
87
|
-
## Related Documentation
|
|
88
|
-
|
|
89
|
-
- **usePremium**: Simplified premium checking
|
|
90
|
-
- **useSubscriptionStatus**: Detailed subscription status
|
|
91
|
-
- **useSubscriptionDetails**: Package and pricing info
|
|
92
|
-
- **useUserTier**: Tier information
|
|
93
|
-
- **Subscription Repository**: `src/infrastructure/repositories/README.md`
|
|
94
|
-
- **Domain Layer**: `src/domain/README.md`
|