@umituz/react-native-subscription 2.27.92 → 2.27.94
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/credits/application/CreditsInitializer.ts +99 -40
- package/src/domains/credits/application/DeductCreditsCommand.ts +31 -13
- package/src/domains/credits/application/PurchaseMetadataGenerator.ts +17 -23
- package/src/domains/credits/core/Credits.ts +39 -39
- package/src/domains/credits/core/CreditsMapper.ts +11 -10
- package/src/domains/credits/core/UserCreditsDocument.ts +33 -33
- package/src/domains/credits/infrastructure/CreditsRepository.ts +46 -59
- package/src/domains/paywall/components/PaywallModal.tsx +1 -1
- package/src/domains/subscription/application/SubscriptionInitializer.ts +59 -18
- package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +20 -20
- package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +46 -27
- package/src/domains/subscription/infrastructure/managers/SubscriptionManager.ts +106 -42
- package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +4 -2
- package/src/domains/subscription/infrastructure/services/RevenueCatInitializer.ts +1 -2
- package/src/domains/subscription/infrastructure/utils/RenewalDetector.ts +1 -1
- package/src/domains/subscription/presentation/components/details/PremiumStatusBadge.tsx +6 -4
- package/src/domains/subscription/presentation/components/feedback/PaywallFeedbackModal.tsx +1 -1
- package/src/domains/subscription/presentation/types/SubscriptionDetailTypes.ts +4 -2
- package/src/domains/subscription/presentation/types/SubscriptionSettingsTypes.ts +1 -1
- package/src/domains/subscription/presentation/usePremiumGate.ts +1 -1
- package/src/domains/subscription/presentation/useSavedPurchaseAutoExecution.ts +1 -1
- package/src/domains/subscription/presentation/useSubscriptionSettingsConfig.ts +4 -3
- package/src/domains/subscription/presentation/useSubscriptionSettingsConfig.utils.ts +1 -1
- package/src/domains/trial/application/TrialEligibilityService.ts +1 -1
- package/src/domains/trial/infrastructure/DeviceTrialRepository.ts +2 -2
- package/src/shared/application/ports/IRevenueCatService.ts +2 -0
- package/src/shared/infrastructure/SubscriptionEventBus.ts +5 -2
- package/src/presentation/README.md +0 -125
- package/src/presentation/hooks/README.md +0 -156
- package/src/presentation/hooks/useAuthSubscriptionSync.md +0 -94
- package/src/presentation/hooks/useCredits.md +0 -103
- package/src/presentation/hooks/useDeductCredit.md +0 -100
- package/src/presentation/hooks/useFeatureGate.md +0 -112
- package/src/presentation/hooks/usePaywall.md +0 -89
- package/src/presentation/hooks/usePaywallOperations.md +0 -92
- package/src/presentation/hooks/usePaywallVisibility.md +0 -95
- package/src/presentation/hooks/usePremium.md +0 -88
- package/src/presentation/hooks/useSubscriptionSettingsConfig.md +0 -94
|
@@ -6,10 +6,12 @@
|
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
7
|
import { View, StyleSheet } from "react-native";
|
|
8
8
|
import { useAppDesignTokens, AtomicText } from "@umituz/react-native-design-system";
|
|
9
|
-
import {
|
|
10
|
-
SUBSCRIPTION_STATUS,
|
|
11
|
-
type SubscriptionStatusType
|
|
12
|
-
} from "../../../
|
|
9
|
+
import {
|
|
10
|
+
SUBSCRIPTION_STATUS,
|
|
11
|
+
type SubscriptionStatusType
|
|
12
|
+
} from "../../../core/SubscriptionConstants";
|
|
13
|
+
|
|
14
|
+
export type { SubscriptionStatusType };
|
|
13
15
|
|
|
14
16
|
export interface PremiumStatusBadgeProps {
|
|
15
17
|
status: SubscriptionStatusType;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useMemo } from "react";
|
|
2
2
|
import { View, TouchableOpacity, TextInput } from "react-native";
|
|
3
3
|
import { AtomicText, BaseModal, useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
4
|
-
import { usePaywallFeedback } from "
|
|
4
|
+
import { usePaywallFeedback } from "../../../../../presentation/hooks/feedback/usePaywallFeedback";
|
|
5
5
|
import { createPaywallFeedbackStyles } from "./paywallFeedbackStyles";
|
|
6
6
|
|
|
7
7
|
const FEEDBACK_OPTION_IDS = [
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Type definitions for subscription detail screen and components
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { SubscriptionStatusType } from "../../
|
|
6
|
+
import type { SubscriptionStatusType } from "../../core/SubscriptionStatus";
|
|
7
7
|
import type { CreditInfo } from "../components/details/PremiumDetailsCardTypes";
|
|
8
8
|
|
|
9
9
|
export type { SubscriptionStatusType, CreditInfo };
|
|
@@ -16,6 +16,8 @@ export interface SubscriptionDetailTranslations {
|
|
|
16
16
|
statusExpired: string;
|
|
17
17
|
statusInactive: string;
|
|
18
18
|
statusCanceled: string;
|
|
19
|
+
/** Free status label */
|
|
20
|
+
statusFree: string;
|
|
19
21
|
/** Trial status label (defaults to statusActive if not provided) */
|
|
20
22
|
statusTrial?: string;
|
|
21
23
|
/** Trial canceled status label (defaults to statusCanceled if not provided) */
|
|
@@ -109,7 +111,7 @@ export interface SubscriptionHeaderProps {
|
|
|
109
111
|
| "expiresLabel"
|
|
110
112
|
| "purchasedLabel"
|
|
111
113
|
| "lifetimeLabel"
|
|
112
|
-
|
|
114
|
+
> & { statusFree: string };
|
|
113
115
|
}
|
|
114
116
|
|
|
115
117
|
/** Props for credits list component */
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Type definitions for subscription settings configuration
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import type { SubscriptionStatusType } from "../../
|
|
6
|
+
import type { SubscriptionStatusType } from "../../core/SubscriptionConstants";
|
|
7
7
|
import type {
|
|
8
8
|
SubscriptionDetailConfig,
|
|
9
9
|
UpgradePromptConfig,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
import { getSavedPurchase, clearSavedPurchase } from "./useAuthAwarePurchase";
|
|
13
13
|
import { usePremium } from "./usePremium";
|
|
14
14
|
import { SubscriptionManager } from "../infrastructure/managers/SubscriptionManager";
|
|
15
|
-
import { usePurchaseLoadingStore } from "
|
|
15
|
+
import { usePurchaseLoadingStore } from "./stores";
|
|
16
16
|
|
|
17
17
|
export interface UseSavedPurchaseAutoExecutionParams {
|
|
18
18
|
onSuccess?: () => void;
|
|
@@ -7,21 +7,21 @@ import { useMemo, useCallback } from "react";
|
|
|
7
7
|
import { useCredits } from "../../credits/presentation/useCredits";
|
|
8
8
|
import { usePaywallVisibility } from "./usePaywallVisibility";
|
|
9
9
|
import { calculateDaysRemaining } from "../core/SubscriptionStatus";
|
|
10
|
-
import { formatDate } from "
|
|
10
|
+
import { formatDate } from "./utils/subscriptionDateUtils";
|
|
11
11
|
import { useCreditsArray, getSubscriptionStatusType } from "./useSubscriptionSettingsConfig.utils";
|
|
12
12
|
import { getCreditsConfig } from "../../credits/infrastructure/CreditsRepositoryProvider";
|
|
13
13
|
import type {
|
|
14
14
|
SubscriptionSettingsConfig,
|
|
15
15
|
SubscriptionStatusType,
|
|
16
16
|
UseSubscriptionSettingsConfigParams,
|
|
17
|
-
} from "
|
|
17
|
+
} from "./types/SubscriptionSettingsTypes";
|
|
18
18
|
|
|
19
19
|
export type {
|
|
20
20
|
SubscriptionSettingsConfig,
|
|
21
21
|
SubscriptionSettingsItemConfig,
|
|
22
22
|
SubscriptionSettingsTranslations,
|
|
23
23
|
UseSubscriptionSettingsConfigParams,
|
|
24
|
-
} from "
|
|
24
|
+
} from "./types/SubscriptionSettingsTypes";
|
|
25
25
|
|
|
26
26
|
export const useSubscriptionSettingsConfig = (
|
|
27
27
|
params: Omit<UseSubscriptionSettingsConfigParams, 'userId'>
|
|
@@ -95,6 +95,7 @@ export const useSubscriptionSettingsConfig = (
|
|
|
95
95
|
statusExpired: translations.statusExpired,
|
|
96
96
|
statusInactive: translations.statusInactive,
|
|
97
97
|
statusCanceled: translations.statusCanceled,
|
|
98
|
+
statusFree: translations.statusInactive,
|
|
98
99
|
expiresLabel: translations.expiresLabel,
|
|
99
100
|
purchasedLabel: translations.purchasedLabel,
|
|
100
101
|
lifetimeLabel: translations.lifetimeLabel,
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
import { useMemo } from "react";
|
|
7
7
|
import type { UserCredits } from "../../credits/core/Credits";
|
|
8
8
|
import { resolveSubscriptionStatus, type PeriodType, type SubscriptionStatusType } from "../core/SubscriptionStatus";
|
|
9
|
-
import type { SubscriptionSettingsTranslations } from "
|
|
9
|
+
import type { SubscriptionSettingsTranslations } from "./types/SubscriptionSettingsTypes";
|
|
10
10
|
|
|
11
11
|
export interface CreditsInfo {
|
|
12
12
|
id: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { doc, getDoc, setDoc, serverTimestamp,
|
|
1
|
+
import { doc, getDoc, setDoc, serverTimestamp, type Firestore } from "firebase/firestore";
|
|
2
2
|
import { getFirestore } from "@umituz/react-native-firebase";
|
|
3
|
-
import type { DeviceTrialRecord } from "
|
|
3
|
+
import type { DeviceTrialRecord } from "../core/TrialTypes";
|
|
4
4
|
|
|
5
5
|
const DEVICE_TRIALS_COLLECTION = "device_trials";
|
|
6
6
|
|
|
@@ -22,10 +22,13 @@ export class SubscriptionEventBus {
|
|
|
22
22
|
this.listeners[event] = [];
|
|
23
23
|
}
|
|
24
24
|
this.listeners[event].push(callback);
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
// Return unsubscribe function
|
|
27
27
|
return () => {
|
|
28
|
-
|
|
28
|
+
const listeners = this.listeners[event];
|
|
29
|
+
if (listeners) {
|
|
30
|
+
this.listeners[event] = listeners.filter(l => l !== callback);
|
|
31
|
+
}
|
|
29
32
|
};
|
|
30
33
|
}
|
|
31
34
|
|
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
# Presentation Layer
|
|
2
|
-
|
|
3
|
-
UI/UX layer for the subscription system - React hooks, components, and screens.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Directory**: `src/presentation/`
|
|
8
|
-
|
|
9
|
-
**Type**: Layer
|
|
10
|
-
|
|
11
|
-
## Strategy
|
|
12
|
-
|
|
13
|
-
### Layer Responsibilities
|
|
14
|
-
|
|
15
|
-
The Presentation Layer is responsible for:
|
|
16
|
-
|
|
17
|
-
1. **State Management**
|
|
18
|
-
- React hooks for data fetching and mutations
|
|
19
|
-
- TanStack Query for server state management
|
|
20
|
-
- Local state management for UI state
|
|
21
|
-
|
|
22
|
-
2. **UI Components**
|
|
23
|
-
- Reusable subscription components
|
|
24
|
-
- Feature gating UI elements
|
|
25
|
-
- Credit display components
|
|
26
|
-
- Paywall components
|
|
27
|
-
|
|
28
|
-
3. **User Interaction**
|
|
29
|
-
- Handle user actions
|
|
30
|
-
- Display appropriate feedback
|
|
31
|
-
- Guide users through purchase flows
|
|
32
|
-
- Show upgrade prompts at right time
|
|
33
|
-
|
|
34
|
-
### Architecture Pattern
|
|
35
|
-
|
|
36
|
-
The presentation layer follows a layered architecture where:
|
|
37
|
-
- Hooks manage state and data fetching at the top level
|
|
38
|
-
- Components consume hooks and render UI
|
|
39
|
-
- Screens compose multiple components together
|
|
40
|
-
- All layers communicate with the domain layer for business logic
|
|
41
|
-
|
|
42
|
-
### Integration Points
|
|
43
|
-
|
|
44
|
-
- **Domain Layer**: Business logic and data access
|
|
45
|
-
- **TanStack Query**: Server state management
|
|
46
|
-
- **RevenueCat**: Purchase operations
|
|
47
|
-
- **Navigation**: Screen routing
|
|
48
|
-
|
|
49
|
-
## Restrictions
|
|
50
|
-
|
|
51
|
-
### REQUIRED
|
|
52
|
-
|
|
53
|
-
- **Type Safety**: All components MUST be typed with TypeScript
|
|
54
|
-
- **Error Boundaries**: MUST implement error boundaries for all screens
|
|
55
|
-
- **Loading States**: MUST show loading indicators during async operations
|
|
56
|
-
- **User Feedback**: MUST provide feedback for all user actions
|
|
57
|
-
|
|
58
|
-
### PROHIBITED
|
|
59
|
-
|
|
60
|
-
- **NEVER** include business logic in components (use hooks instead)
|
|
61
|
-
- **NEVER** make direct API calls from components (use hooks)
|
|
62
|
-
- **DO NOT** store sensitive data in component state
|
|
63
|
-
- **NEVER** hardcode strings (use localization)
|
|
64
|
-
|
|
65
|
-
### CRITICAL SAFETY
|
|
66
|
-
|
|
67
|
-
- **ALWAYS** validate props before rendering
|
|
68
|
-
- **ALWAYS** handle loading and error states
|
|
69
|
-
- **NEVER** trust client-side state for security decisions
|
|
70
|
-
- **MUST** implement proper error boundaries
|
|
71
|
-
- **ALWAYS** sanitize user inputs before display
|
|
72
|
-
|
|
73
|
-
## AI Agent Guidelines
|
|
74
|
-
|
|
75
|
-
### When Building Presentation Layer
|
|
76
|
-
|
|
77
|
-
1. **Always** use hooks for data fetching and state management
|
|
78
|
-
2. **Always** handle loading and error states
|
|
79
|
-
3. **Always** provide user feedback for actions
|
|
80
|
-
4. **Always** implement error boundaries
|
|
81
|
-
5. **Never** include business logic in components
|
|
82
|
-
|
|
83
|
-
### Integration Checklist
|
|
84
|
-
|
|
85
|
-
- [ ] Use appropriate hooks for data access
|
|
86
|
-
- [ ] Handle loading states
|
|
87
|
-
- [ ] Handle error states
|
|
88
|
-
- [ ] Implement error boundaries
|
|
89
|
-
- [ ] Provide user feedback
|
|
90
|
-
- [ ] Test with various data states
|
|
91
|
-
- [ ] Test error scenarios
|
|
92
|
-
- [ ] Ensure type safety
|
|
93
|
-
- [ ] Use localization for all strings
|
|
94
|
-
- [ ] Test accessibility
|
|
95
|
-
|
|
96
|
-
### Common Patterns
|
|
97
|
-
|
|
98
|
-
1. **Compound Components**: Build complex UIs from simple components
|
|
99
|
-
2. **Render Props**: Share stateful logic between components
|
|
100
|
-
3. **Custom Hooks**: Extract reusable stateful logic
|
|
101
|
-
4. **Error Boundaries**: Prevent crashes from propagating
|
|
102
|
-
5. **Loading Skeletons**: Show placeholder during loading
|
|
103
|
-
6. **Optimistic Updates**: Update UI immediately, rollback on failure
|
|
104
|
-
7. **Graceful Degradation**: Show limited version on error
|
|
105
|
-
8. **Responsive Design**: Support different screen sizes
|
|
106
|
-
|
|
107
|
-
## Related Documentation
|
|
108
|
-
|
|
109
|
-
- **Hooks**: `hooks/README.md`
|
|
110
|
-
- **Components**: `components/README.md`
|
|
111
|
-
- **Screens**: `screens/README.md`
|
|
112
|
-
- **Wallet Domain**: `../../domains/wallet/README.md`
|
|
113
|
-
- **Paywall Domain**: `../../domains/paywall/README.md`
|
|
114
|
-
- **RevenueCat**: `../../revenuecat/README.md`
|
|
115
|
-
|
|
116
|
-
## Directory Structure
|
|
117
|
-
|
|
118
|
-
The presentation layer contains:
|
|
119
|
-
- **hooks/** - React hooks for state management (usePremium, useSubscription, useCredits, useDeductCredit, useFeatureGate)
|
|
120
|
-
- **components/** - UI components organized by functionality
|
|
121
|
-
- **details/** - Detail cards, badges
|
|
122
|
-
- **feedback/** - Modals, feedback components
|
|
123
|
-
- **sections/** - Section components
|
|
124
|
-
- **paywall/** - Paywall components
|
|
125
|
-
- **screens/** - Full-screen components (SubscriptionDetailScreen)
|
|
@@ -1,156 +0,0 @@
|
|
|
1
|
-
# Subscription Hooks
|
|
2
|
-
|
|
3
|
-
Collection of React hooks for subscription, premium, and credits management.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**Directory**: `src/presentation/hooks/`
|
|
10
|
-
|
|
11
|
-
**Type**: Hooks Collection
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Hook Organization
|
|
16
|
-
|
|
17
|
-
Hooks are organized by functionality:
|
|
18
|
-
|
|
19
|
-
1. **Subscription Hooks**: Manage subscription status and details
|
|
20
|
-
2. **Premium Hooks**: Check and manage premium access
|
|
21
|
-
3. **Credits Hooks**: Handle credit balance and operations
|
|
22
|
-
4. **Gate Hooks**: Control feature access based on user state
|
|
23
|
-
5. **Auth Hooks**: Authentication-aware purchase flows
|
|
24
|
-
6. **Paywall Hooks**: Paywall display and management
|
|
25
|
-
|
|
26
|
-
### Integration Pattern
|
|
27
|
-
|
|
28
|
-
All hooks follow consistent patterns:
|
|
29
|
-
- Return loading, error, and data states
|
|
30
|
-
- Provide refetch/refresh functions
|
|
31
|
-
- Use TanStack Query for caching
|
|
32
|
-
- Handle optimistic updates
|
|
33
|
-
- Support real-time updates
|
|
34
|
-
|
|
35
|
-
## Hook Categories
|
|
36
|
-
|
|
37
|
-
### Subscription Hooks
|
|
38
|
-
|
|
39
|
-
- **useSubscription**: Core subscription status management
|
|
40
|
-
- **useSubscriptionStatus**: Detailed subscription status
|
|
41
|
-
- **useSubscriptionDetails**: Subscription package and feature details
|
|
42
|
-
- **useSubscriptionSettingsConfig**: Settings and configuration
|
|
43
|
-
|
|
44
|
-
### Premium Hooks
|
|
45
|
-
|
|
46
|
-
- **usePremium**: Premium status checker
|
|
47
|
-
- **usePremiumGate**: Premium feature gating
|
|
48
|
-
- **usePremiumWithCredits**: Hybrid premium/credits access
|
|
49
|
-
|
|
50
|
-
### Credits Hooks
|
|
51
|
-
|
|
52
|
-
- **useCredits**: Credit balance and transactions
|
|
53
|
-
- **useCreditChecker**: Simple credit validation
|
|
54
|
-
- **useDeductCredit**: Credit deduction with optimistic updates
|
|
55
|
-
- **useInitializeCredits**: Initialize credits after purchase
|
|
56
|
-
|
|
57
|
-
### Gate Hooks
|
|
58
|
-
|
|
59
|
-
- **useFeatureGate**: Unified auth, subscription, and credits gating
|
|
60
|
-
- **useSubscriptionGate**: Subscription-only gating
|
|
61
|
-
- **useCreditsGate**: Credits-only gating
|
|
62
|
-
- **usePremiumGate**: Premium-only gating
|
|
63
|
-
- **useAuthGate**: Authentication gating
|
|
64
|
-
|
|
65
|
-
### Auth Hooks
|
|
66
|
-
|
|
67
|
-
- **useAuthAwarePurchase**: Authentication-aware purchase flow
|
|
68
|
-
- **useAuthSubscriptionSync**: Auth and subscription synchronization
|
|
69
|
-
|
|
70
|
-
### Paywall Hooks
|
|
71
|
-
|
|
72
|
-
- **usePaywall**: Paywall display management
|
|
73
|
-
- **usePaywallOperations**: Paywall show/hide operations
|
|
74
|
-
- **usePaywallVisibility**: Paywall visibility rules
|
|
75
|
-
|
|
76
|
-
### User Tier Hooks
|
|
77
|
-
|
|
78
|
-
- **useUserTier**: User tier management
|
|
79
|
-
- **useUserTierWithRepository**: Repository-based tier management
|
|
80
|
-
|
|
81
|
-
### Development Hooks
|
|
82
|
-
|
|
83
|
-
- **useDevTestCallbacks**: Development and testing utilities
|
|
84
|
-
|
|
85
|
-
## Restrictions
|
|
86
|
-
|
|
87
|
-
### REQUIRED
|
|
88
|
-
|
|
89
|
-
- **Import Path**: MUST import from `@umituz/react-native-subscription`
|
|
90
|
-
- **Loading States**: MUST handle loading state in UI
|
|
91
|
-
- **Error Handling**: MUST handle error state
|
|
92
|
-
- **User Authentication**: Most hooks require authenticated user
|
|
93
|
-
|
|
94
|
-
### PROHIBITED
|
|
95
|
-
|
|
96
|
-
- **NEVER** use hooks outside React components
|
|
97
|
-
- **NEVER** ignore loading states
|
|
98
|
-
- **NEVER** skip error handling
|
|
99
|
-
- **DO NOT** use hook returns for security decisions (server-side validation required)
|
|
100
|
-
|
|
101
|
-
### CRITICAL SAFETY
|
|
102
|
-
|
|
103
|
-
- **ALWAYS** handle loading and error states
|
|
104
|
-
- **NEVER** trust client-side state for security
|
|
105
|
-
- **MUST** implement error boundaries
|
|
106
|
-
- **ALWAYS** test with various user states (anonymous, free, premium)
|
|
107
|
-
|
|
108
|
-
## AI Agent Guidelines
|
|
109
|
-
|
|
110
|
-
### When Using Subscription Hooks
|
|
111
|
-
|
|
112
|
-
1. **Always** handle loading and error states
|
|
113
|
-
2. **Always** use appropriate gate hooks for feature access
|
|
114
|
-
3. **Always** provide user feedback for all operations
|
|
115
|
-
4. **Never** trust client-side state for security
|
|
116
|
-
5. **Always** test with different user tiers
|
|
117
|
-
|
|
118
|
-
### Integration Checklist
|
|
119
|
-
|
|
120
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
121
|
-
- [ ] Choose appropriate hook for use case
|
|
122
|
-
- [ ] Handle loading state
|
|
123
|
-
- [ ] Handle error state
|
|
124
|
-
- [ ] Implement error boundaries
|
|
125
|
-
- [ ] Use gate hooks for feature access
|
|
126
|
-
- [ ] Test with all user tiers
|
|
127
|
-
- [ ] Test offline scenarios
|
|
128
|
-
- [ ] Test error scenarios
|
|
129
|
-
|
|
130
|
-
### Common Patterns
|
|
131
|
-
|
|
132
|
-
1. **Feature Gating**: Use `useFeatureGate` for unified access control
|
|
133
|
-
2. **Credit Operations**: Check → Deduct → Execute pattern
|
|
134
|
-
3. **Subscription Display**: Show status, expiration, renewal info
|
|
135
|
-
4. **Premium Features**: Gate content, provide upgrade path
|
|
136
|
-
5. **Paywall Integration**: Automatic display on access denial
|
|
137
|
-
6. **Real-time Updates**: Refresh on focus, background sync
|
|
138
|
-
|
|
139
|
-
## Related Documentation
|
|
140
|
-
|
|
141
|
-
- **Subscription Domain**: `src/domains/wallet/README.md`
|
|
142
|
-
- **Paywall Domain**: `src/domains/paywall/README.md`
|
|
143
|
-
- **Config Domain**: `src/domains/config/README.md`
|
|
144
|
-
- **RevenueCat Integration**: `src/revenuecat/README.md`
|
|
145
|
-
- **Presentation Components**: `src/presentation/components/README.md`
|
|
146
|
-
|
|
147
|
-
## Individual Hook Documentation
|
|
148
|
-
|
|
149
|
-
- [useDeductCredit](./useDeductCredit.md) - Credit deduction with optimistic updates
|
|
150
|
-
- [useCredits](./useCredits.md) - Credit balance access
|
|
151
|
-
- [useCreditChecker](./useCreditChecker.md) - Simple credit validation
|
|
152
|
-
- [useFeatureGate](./useFeatureGate.md) - Unified feature gating
|
|
153
|
-
- [useSubscription](./useSubscription.md) - Subscription status management
|
|
154
|
-
- [usePremium](./usePremium.md) - Premium status checker
|
|
155
|
-
- [useCreditsGate](./useCreditsGate.md) - Credits-based feature gating
|
|
156
|
-
- [useInitializeCredits](./useInitializeCredits.md) - Initialize credits after purchase
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
# useAuthSubscriptionSync Hook
|
|
2
|
-
|
|
3
|
-
Automatically synchronizes subscription state with authentication changes.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/useAuthSubscriptionSync.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Auth-Subscription Synchronization
|
|
16
|
-
|
|
17
|
-
1. **Auth Listener Setup**: Subscribe to auth state changes via provided callback
|
|
18
|
-
2. **User Change Detection**: Detect when userId changes (including sign out)
|
|
19
|
-
3. **Subscription Initialization**: Initialize subscription when user signs in
|
|
20
|
-
4. **One-Time Init**: Only initialize once per user session (skips duplicates)
|
|
21
|
-
5. **User Switching**: Re-initialize when switching between accounts
|
|
22
|
-
6. **Cleanup**: Unsubscribe from auth listener on unmount
|
|
23
|
-
|
|
24
|
-
### Integration Points
|
|
25
|
-
|
|
26
|
-
- **Auth Provider**: Any auth system (Firebase, Auth0, custom)
|
|
27
|
-
- **RevenueCat**: For subscription initialization with logIn
|
|
28
|
-
- **Subscription Service**: Backend subscription sync
|
|
29
|
-
- **Credits System**: Optional credits initialization
|
|
30
|
-
- **App Root**: Should be placed in root App component
|
|
31
|
-
|
|
32
|
-
## Restrictions
|
|
33
|
-
|
|
34
|
-
### REQUIRED
|
|
35
|
-
|
|
36
|
-
- **Auth State Change Callback**: MUST provide onAuthStateChanged function
|
|
37
|
-
- **Subscription Init**: MUST provide initializeSubscription function
|
|
38
|
-
- **App Root Setup**: SHOULD be placed in root App component
|
|
39
|
-
- **Unsubscribe Handling**: Callback MUST return unsubscribe function
|
|
40
|
-
|
|
41
|
-
### PROHIBITED
|
|
42
|
-
|
|
43
|
-
- **NEVER** place in individual screen components (use app root)
|
|
44
|
-
- **NEVER** call without proper auth callback
|
|
45
|
-
- **DO NOT** manually call initializeSubscription (hook handles it)
|
|
46
|
-
- **DO NOT** configure multiple times (one-time setup)
|
|
47
|
-
|
|
48
|
-
### CRITICAL SAFETY
|
|
49
|
-
|
|
50
|
-
- **ALWAYS** configure at app root level
|
|
51
|
-
- **MUST** handle user switching correctly
|
|
52
|
-
- **ALWAYS** return unsubscribe function from callback
|
|
53
|
-
- **NEVER** rely on manual subscription initialization
|
|
54
|
-
|
|
55
|
-
## AI Agent Guidelines
|
|
56
|
-
|
|
57
|
-
### When Implementing Auth-Subscription Sync
|
|
58
|
-
|
|
59
|
-
1. **Always** place in root App component
|
|
60
|
-
2. **Always** provide onAuthStateChanged that returns unsubscribe
|
|
61
|
-
3. **Always** provide initializeSubscription for user ID
|
|
62
|
-
4. **Always** test user switching scenarios
|
|
63
|
-
5. **Never** place in child components
|
|
64
|
-
|
|
65
|
-
### Integration Checklist
|
|
66
|
-
|
|
67
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
68
|
-
- [ ] Place in root App component
|
|
69
|
-
- [ ] Provide onAuthStateChanged callback
|
|
70
|
-
- [ ] Ensure callback returns unsubscribe function
|
|
71
|
-
- [ ] Provide initializeSubscription function
|
|
72
|
-
- [ ] Test with initial user sign-in
|
|
73
|
-
- [ ] Test with user sign-out
|
|
74
|
-
- [ ] Test with account switching
|
|
75
|
-
- [ ] Verify subscription initializes only once per user
|
|
76
|
-
- [ ] Test cleanup on unmount
|
|
77
|
-
|
|
78
|
-
### Common Patterns
|
|
79
|
-
|
|
80
|
-
1. **Firebase + RevenueCat**: Sync Firebase auth with RevenueCat
|
|
81
|
-
2. **Custom Auth + Backend**: Use custom auth with backend sync
|
|
82
|
-
3. **Multi-Service Setup**: Initialize multiple services (RevenueCat, credits, backend)
|
|
83
|
-
4. **Error Handling**: Handle initialization failures gracefully
|
|
84
|
-
5. **Loading State**: Show loading during sync
|
|
85
|
-
6. **Analytics Tracking**: Track auth and subscription events
|
|
86
|
-
|
|
87
|
-
## Related Documentation
|
|
88
|
-
|
|
89
|
-
- **useAuth**: For authentication state
|
|
90
|
-
- **usePremium**: For subscription status
|
|
91
|
-
- **useAuthAwarePurchase**: For auth-gated purchases
|
|
92
|
-
- **useUserTier**: For tier determination
|
|
93
|
-
- **Auth Integration Guide**: `src/docs/AUTH_INTEGRATION.md`
|
|
94
|
-
- **RevenueCat Setup**: `src/docs/REVENUECAT_SETUP.md`
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
# useCredits Hook
|
|
2
|
-
|
|
3
|
-
Hook for accessing and managing credits balance with real-time updates.
|
|
4
|
-
|
|
5
|
-
## Location
|
|
6
|
-
|
|
7
|
-
**Import Path**: `@umituz/react-native-subscription`
|
|
8
|
-
|
|
9
|
-
**File**: `src/presentation/hooks/useCredits.ts`
|
|
10
|
-
|
|
11
|
-
**Type**: Hook
|
|
12
|
-
|
|
13
|
-
## Strategy
|
|
14
|
-
|
|
15
|
-
### Data Fetching Flow
|
|
16
|
-
|
|
17
|
-
1. **Initial Load**
|
|
18
|
-
- Fetch credits from repository on mount
|
|
19
|
-
- Cache results in TanStack Query
|
|
20
|
-
- Handle loading/error states
|
|
21
|
-
|
|
22
|
-
2. **Real-time Updates**
|
|
23
|
-
- Subscribe to credit changes via repository listener
|
|
24
|
-
- Auto-update on balance changes
|
|
25
|
-
- Invalidate query on external modifications
|
|
26
|
-
|
|
27
|
-
3. **Cache Management**
|
|
28
|
-
- Use TanStack Query for caching
|
|
29
|
-
- Background refetch on window focus
|
|
30
|
-
- Manual refetch capability
|
|
31
|
-
|
|
32
|
-
### Integration Points
|
|
33
|
-
|
|
34
|
-
- **Credits Repository**: `src/domains/wallet/infrastructure/repositories/CreditsRepository.ts`
|
|
35
|
-
- **Credits Entity**: `src/domains/wallet/domain/entities/UserCredits.ts`
|
|
36
|
-
- **TanStack Query**: For cache management and background updates
|
|
37
|
-
- **useFocusEffect**: For refresh on screen focus
|
|
38
|
-
|
|
39
|
-
## Restrictions
|
|
40
|
-
|
|
41
|
-
### REQUIRED
|
|
42
|
-
|
|
43
|
-
- **User Authentication**: User MUST be authenticated to access credits
|
|
44
|
-
- **Error Handling**: MUST handle error state in UI
|
|
45
|
-
- **Loading State**: MUST show loading indicator while fetching
|
|
46
|
-
|
|
47
|
-
### PROHIBITED
|
|
48
|
-
|
|
49
|
-
- **NEVER** assume credits are available without checking loading state
|
|
50
|
-
- **NEVER** use this hook for unauthenticated users
|
|
51
|
-
- **DO NOT** mutate credits directly - use `useDeductCredit` instead
|
|
52
|
-
- **DO NOT** call refetch excessively (causes unnecessary network calls)
|
|
53
|
-
|
|
54
|
-
### CRITICAL SAFETY
|
|
55
|
-
|
|
56
|
-
- **ALWAYS** check `isLoading` before displaying credits
|
|
57
|
-
- **ALWAYS** handle `error` state to prevent crashes
|
|
58
|
-
- **NEVER** use `credits` value for security decisions (validate on backend)
|
|
59
|
-
- **MUST** implement error boundaries when displaying balance
|
|
60
|
-
|
|
61
|
-
## AI Agent Guidelines
|
|
62
|
-
|
|
63
|
-
### When Implementing Credit Displays
|
|
64
|
-
|
|
65
|
-
1. **Always** handle loading state explicitly
|
|
66
|
-
2. **Always** handle error state gracefully
|
|
67
|
-
3. **Always** provide manual refresh option
|
|
68
|
-
4. **Always** format balance safely (handle undefined/null)
|
|
69
|
-
5. **Never** use credits for security decisions (server-side validation required)
|
|
70
|
-
|
|
71
|
-
### Integration Checklist
|
|
72
|
-
|
|
73
|
-
- [ ] Import from correct path: `@umituz/react-native-subscription`
|
|
74
|
-
- [ ] Handle loading state in UI
|
|
75
|
-
- [ ] Handle error state in UI
|
|
76
|
-
- [ ] Provide refresh mechanism
|
|
77
|
-
- [ ] Format balance safely with default values
|
|
78
|
-
- [ ] Implement error boundaries
|
|
79
|
-
- [ ] Test with no credits (zero balance)
|
|
80
|
-
- [ ] Test with loading states
|
|
81
|
-
- [ ] Test with error states
|
|
82
|
-
- [ ] Test refresh functionality
|
|
83
|
-
|
|
84
|
-
### Common Patterns to Implement
|
|
85
|
-
|
|
86
|
-
1. **Balance Card**: Display credits with currency conversion
|
|
87
|
-
2. **Transaction List**: Show recent credit activity
|
|
88
|
-
3. **Low Credits Warning**: Alert when balance is low
|
|
89
|
-
4. **Refresh Control**: Pull-to-refresh or button
|
|
90
|
-
5. **Real-time Updates**: Use focus effect for auto-refresh
|
|
91
|
-
6. **Purchase Prompt**: Link to credit packages when low
|
|
92
|
-
7. **Skeletal Loading**: Show skeleton during initial load
|
|
93
|
-
8. **Error Recovery**: Retry mechanism for failed fetches
|
|
94
|
-
|
|
95
|
-
## Related Documentation
|
|
96
|
-
|
|
97
|
-
- **useDeductCredit**: Deduct credits from balance
|
|
98
|
-
- **useCreditChecker**: Check credit availability before operations
|
|
99
|
-
- **useInitializeCredits**: Initialize credits after purchase
|
|
100
|
-
- **useCreditsGate**: Gate features behind credit requirements
|
|
101
|
-
- **useFeatureGate**: Unified feature gating with credits
|
|
102
|
-
- **Credits Repository**: `src/domains/wallet/infrastructure/repositories/README.md`
|
|
103
|
-
- **Wallet Domain**: `src/domains/wallet/README.md`
|