@umituz/react-native-subscription 2.40.14 → 2.40.15
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.40.
|
|
3
|
+
"version": "2.40.15",
|
|
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",
|
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Subscription Flow
|
|
2
|
+
* Subscription Flow Store
|
|
3
3
|
* Manages the high-level application flow: Splash -> Onboarding -> Paywall -> Main App.
|
|
4
|
-
*
|
|
4
|
+
* Uses @umituz/react-native-design-system's storage utility for standardized persistence.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
import { useState, useEffect, useCallback } from "react";
|
|
8
7
|
import { DeviceEventEmitter } from "react-native";
|
|
9
|
-
import
|
|
10
|
-
|
|
11
|
-
const PAYWALL_SHOWN_KEY = "post_onboarding_paywall_shown";
|
|
12
|
-
const ONBOARDING_KEY = "onboarding_complete";
|
|
8
|
+
import { createStore } from "@umituz/react-native-design-system/storage";
|
|
13
9
|
|
|
14
10
|
export interface SubscriptionFlowState {
|
|
15
11
|
isInitialized: boolean;
|
|
@@ -20,8 +16,7 @@ export interface SubscriptionFlowState {
|
|
|
20
16
|
isAuthModalOpen: boolean;
|
|
21
17
|
}
|
|
22
18
|
|
|
23
|
-
export interface
|
|
24
|
-
state: SubscriptionFlowState;
|
|
19
|
+
export interface SubscriptionFlowActions {
|
|
25
20
|
completeOnboarding: () => Promise<void>;
|
|
26
21
|
closePostOnboardingPaywall: () => Promise<void>;
|
|
27
22
|
closeFeedback: () => void;
|
|
@@ -29,128 +24,78 @@ export interface UseSubscriptionFlowResult {
|
|
|
29
24
|
markPaywallShown: () => Promise<void>;
|
|
30
25
|
setShowFeedback: (show: boolean) => void;
|
|
31
26
|
resetFlow: () => Promise<void>;
|
|
27
|
+
setInitialized: (initialized: boolean) => void;
|
|
32
28
|
}
|
|
33
29
|
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
console.error("[useSubscriptionFlow] Initialization failed:", error);
|
|
61
|
-
setState((prev) => ({ ...prev, isInitialized: true }));
|
|
62
|
-
}
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
init();
|
|
66
|
-
|
|
67
|
-
// Listen for global onboarding completion events (e.g. from standalone onboarding components)
|
|
68
|
-
const subscription = DeviceEventEmitter.addListener(
|
|
69
|
-
"onboarding-complete",
|
|
70
|
-
() => {
|
|
71
|
-
setState((prev) => ({ ...prev, isOnboardingComplete: true }));
|
|
72
|
-
AsyncStorage.setItem(ONBOARDING_KEY, "true");
|
|
73
|
-
}
|
|
74
|
-
);
|
|
75
|
-
|
|
76
|
-
return () => subscription.remove();
|
|
77
|
-
}, []);
|
|
78
|
-
|
|
79
|
-
const completeOnboarding = useCallback(async () => {
|
|
80
|
-
try {
|
|
81
|
-
await AsyncStorage.setItem(ONBOARDING_KEY, "true");
|
|
82
|
-
setState((prev) => ({
|
|
83
|
-
...prev,
|
|
30
|
+
export type SubscriptionFlowStore = SubscriptionFlowState & SubscriptionFlowActions;
|
|
31
|
+
|
|
32
|
+
const initialState: SubscriptionFlowState = {
|
|
33
|
+
isInitialized: false,
|
|
34
|
+
isOnboardingComplete: false,
|
|
35
|
+
showPostOnboardingPaywall: false,
|
|
36
|
+
showFeedback: false,
|
|
37
|
+
paywallShown: false,
|
|
38
|
+
isAuthModalOpen: false,
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export const useSubscriptionFlowStore = createStore<SubscriptionFlowState, SubscriptionFlowActions>({
|
|
42
|
+
name: "subscription-flow-storage",
|
|
43
|
+
initialState,
|
|
44
|
+
persist: true,
|
|
45
|
+
// Only persist onboarding and paywall status, other states are transient
|
|
46
|
+
partialize: (state) => ({
|
|
47
|
+
isOnboardingComplete: state.isOnboardingComplete,
|
|
48
|
+
paywallShown: state.paywallShown,
|
|
49
|
+
}),
|
|
50
|
+
onRehydrate: (state) => {
|
|
51
|
+
state.setInitialized(true);
|
|
52
|
+
},
|
|
53
|
+
actions: (set) => ({
|
|
54
|
+
completeOnboarding: async () => {
|
|
55
|
+
set({
|
|
84
56
|
isOnboardingComplete: true,
|
|
85
57
|
showPostOnboardingPaywall: true,
|
|
86
|
-
})
|
|
58
|
+
});
|
|
87
59
|
DeviceEventEmitter.emit("onboarding-complete");
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}, []);
|
|
92
|
-
|
|
93
|
-
const closePostOnboardingPaywall = useCallback(async () => {
|
|
94
|
-
try {
|
|
95
|
-
await AsyncStorage.setItem(PAYWALL_SHOWN_KEY, "true");
|
|
96
|
-
setState((prev) => ({
|
|
97
|
-
...prev,
|
|
60
|
+
},
|
|
61
|
+
closePostOnboardingPaywall: async () => {
|
|
62
|
+
set({
|
|
98
63
|
showPostOnboardingPaywall: false,
|
|
99
64
|
paywallShown: true,
|
|
100
|
-
})
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
const setAuthModalOpen = useCallback((open: boolean) => {
|
|
111
|
-
setState((prev) => ({ ...prev, isAuthModalOpen: open }));
|
|
112
|
-
}, []);
|
|
113
|
-
|
|
114
|
-
const setShowFeedback = useCallback((show: boolean) => {
|
|
115
|
-
setState((prev) => ({ ...prev, showFeedback: show }));
|
|
116
|
-
}, []);
|
|
117
|
-
|
|
118
|
-
const markPaywallShown = useCallback(async () => {
|
|
119
|
-
try {
|
|
120
|
-
await AsyncStorage.setItem(PAYWALL_SHOWN_KEY, "true");
|
|
121
|
-
setState((prev) => ({ ...prev, paywallShown: true }));
|
|
122
|
-
} catch (e) {
|
|
123
|
-
console.error("[useSubscriptionFlow] Failed to mark paywall shown:", e);
|
|
124
|
-
}
|
|
125
|
-
}, []);
|
|
126
|
-
|
|
127
|
-
const resetFlow = useCallback(async () => {
|
|
128
|
-
try {
|
|
129
|
-
await Promise.all([
|
|
130
|
-
AsyncStorage.removeItem(ONBOARDING_KEY),
|
|
131
|
-
AsyncStorage.removeItem(PAYWALL_SHOWN_KEY),
|
|
132
|
-
]);
|
|
133
|
-
setState({
|
|
134
|
-
isInitialized: true,
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
closeFeedback: () => set({ showFeedback: false }),
|
|
68
|
+
setAuthModalOpen: (open: boolean) => set({ isAuthModalOpen: open }),
|
|
69
|
+
setShowFeedback: (show: boolean) => set({ showFeedback: show }),
|
|
70
|
+
markPaywallShown: async () => set({ paywallShown: true }),
|
|
71
|
+
setInitialized: (initialized: boolean) => set({ isInitialized: initialized }),
|
|
72
|
+
resetFlow: async () => {
|
|
73
|
+
set({
|
|
135
74
|
isOnboardingComplete: false,
|
|
136
75
|
showPostOnboardingPaywall: false,
|
|
137
76
|
showFeedback: false,
|
|
138
77
|
paywallShown: false,
|
|
139
78
|
isAuthModalOpen: false,
|
|
140
79
|
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}, []);
|
|
80
|
+
},
|
|
81
|
+
}),
|
|
82
|
+
});
|
|
145
83
|
|
|
84
|
+
/**
|
|
85
|
+
* Hook for backward compatibility and easier consumption.
|
|
86
|
+
* Provides a unified object structure matching the previous implementation.
|
|
87
|
+
*/
|
|
88
|
+
export function useSubscriptionFlow(_userId?: string) {
|
|
89
|
+
const store = useSubscriptionFlowStore();
|
|
90
|
+
|
|
146
91
|
return {
|
|
147
|
-
state,
|
|
148
|
-
completeOnboarding,
|
|
149
|
-
closePostOnboardingPaywall,
|
|
150
|
-
closeFeedback,
|
|
151
|
-
setAuthModalOpen,
|
|
152
|
-
markPaywallShown,
|
|
153
|
-
setShowFeedback,
|
|
154
|
-
resetFlow,
|
|
92
|
+
state: store,
|
|
93
|
+
completeOnboarding: store.completeOnboarding,
|
|
94
|
+
closePostOnboardingPaywall: store.closePostOnboardingPaywall,
|
|
95
|
+
closeFeedback: store.closeFeedback,
|
|
96
|
+
setAuthModalOpen: store.setAuthModalOpen,
|
|
97
|
+
markPaywallShown: store.markPaywallShown,
|
|
98
|
+
setShowFeedback: store.setShowFeedback,
|
|
99
|
+
resetFlow: store.resetFlow,
|
|
155
100
|
};
|
|
156
101
|
}
|
package/src/index.ts
CHANGED
|
@@ -45,8 +45,8 @@ export { useDeductCredit } from "./domains/credits/presentation/deduct-credit/us
|
|
|
45
45
|
export { useFeatureGate } from "./domains/subscription/presentation/useFeatureGate";
|
|
46
46
|
export { usePaywallVisibility, paywallControl } from "./domains/subscription/presentation/usePaywallVisibility";
|
|
47
47
|
export { usePremium } from "./domains/subscription/presentation/usePremium";
|
|
48
|
-
export { useSubscriptionFlow } from "./domains/subscription/presentation/useSubscriptionFlow";
|
|
49
|
-
export type { SubscriptionFlowState,
|
|
48
|
+
export { useSubscriptionFlow, useSubscriptionFlowStore } from "./domains/subscription/presentation/useSubscriptionFlow";
|
|
49
|
+
export type { SubscriptionFlowState, SubscriptionFlowActions, SubscriptionFlowStore } from "./domains/subscription/presentation/useSubscriptionFlow";
|
|
50
50
|
export { useSubscriptionStatus } from "./domains/subscription/presentation/useSubscriptionStatus";
|
|
51
51
|
export * from "./domains/subscription/presentation/useSubscriptionStatus.types";
|
|
52
52
|
export * from "./presentation/hooks/feedback/usePaywallFeedback";
|