@umituz/react-native-subscription 2.43.1 → 2.43.2
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/PaywallScreen.tsx +0 -1
- package/src/domains/paywall/hooks/usePaywallOrchestrator.ts +0 -4
- package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +2 -2
- package/src/domains/subscription/core/events/FlowEvents.ts +24 -0
- package/src/domains/subscription/core/events/SubscriptionEvents.ts +22 -0
- package/src/domains/subscription/presentation/usePremium.ts +1 -6
- package/src/index.ts +7 -4
- package/src/shared/infrastructure/SubscriptionEventBus.ts +6 -18
- package/src/shared/infrastructure/react-query/queryConfig.ts +0 -3
- package/src/domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay.tsx +0 -60
- package/src/domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay.types.ts +0 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.43.
|
|
3
|
+
"version": "2.43.2",
|
|
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",
|
|
@@ -22,9 +22,6 @@ export interface PaywallOrchestratorOptions {
|
|
|
22
22
|
* High-level orchestrator for Paywall navigation.
|
|
23
23
|
* Handles automatic triggers (post-onboarding) and manual triggers (showPaywall state).
|
|
24
24
|
* Centralizes handlers for success, close, and feedback triggers.
|
|
25
|
-
*
|
|
26
|
-
* This orchestrator fetches all subscription data and passes it to PaywallScreen as props.
|
|
27
|
-
* PaywallScreen is now a "dumb" component that doesn't call usePremium internally.
|
|
28
25
|
*/
|
|
29
26
|
export function usePaywallOrchestrator({
|
|
30
27
|
navigation,
|
|
@@ -86,7 +83,6 @@ export function usePaywallOrchestrator({
|
|
|
86
83
|
packagesCount: packages.length
|
|
87
84
|
});
|
|
88
85
|
|
|
89
|
-
// Pass all data and actions as props - PaywallScreen is now a dumb component
|
|
90
86
|
navigation.navigate("PaywallScreen", {
|
|
91
87
|
// UI Props
|
|
92
88
|
translations,
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { PURCHASE_SOURCE, PURCHASE_TYPE } from "../core/SubscriptionConstants";
|
|
2
|
-
import
|
|
2
|
+
import { subscriptionEventBus, SUBSCRIPTION_EVENTS } from "../../../shared/infrastructure/SubscriptionEventBus";
|
|
3
|
+
import type { PurchaseCompletedEvent, RenewalDetectedEvent, PremiumStatusChangedEvent } from "../core/SubscriptionEvents";
|
|
3
4
|
import { getCreditsRepository } from "../../credits/infrastructure/CreditsRepositoryManager";
|
|
4
5
|
import { extractRevenueCatData } from "./SubscriptionSyncUtils";
|
|
5
6
|
import { generatePurchaseId, generateRenewalId } from "./syncIdGenerators";
|
|
6
|
-
import { subscriptionEventBus, SUBSCRIPTION_EVENTS } from "../../../shared/infrastructure/SubscriptionEventBus";
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Central processor for all subscription sync operations.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application flow events
|
|
3
|
+
* Events emitted during high-level application flow transitions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const FLOW_EVENTS = {
|
|
7
|
+
ONBOARDING_COMPLETED: "flow_onboarding_completed",
|
|
8
|
+
PAYWALL_SHOWN: "flow_paywall_shown",
|
|
9
|
+
PAYWALL_CLOSED: "flow_paywall_closed",
|
|
10
|
+
} as const;
|
|
11
|
+
|
|
12
|
+
export type FlowEventType = typeof FLOW_EVENTS[keyof typeof FLOW_EVENTS];
|
|
13
|
+
|
|
14
|
+
export interface OnboardingCompletedEvent {
|
|
15
|
+
timestamp: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface PaywallShownEvent {
|
|
19
|
+
timestamp: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface PaywallClosedEvent {
|
|
23
|
+
timestamp: number;
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subscription-related events
|
|
3
|
+
* Events emitted during subscription lifecycle operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export const SUBSCRIPTION_EVENTS = {
|
|
7
|
+
CREDITS_UPDATED: "credits_updated",
|
|
8
|
+
PURCHASE_COMPLETED: "purchase_completed",
|
|
9
|
+
RENEWAL_DETECTED: "renewal_detected",
|
|
10
|
+
PREMIUM_STATUS_CHANGED: "premium_status_changed",
|
|
11
|
+
SYNC_STATUS_CHANGED: "sync_status_changed",
|
|
12
|
+
} as const;
|
|
13
|
+
|
|
14
|
+
export type SubscriptionEventType = typeof SUBSCRIPTION_EVENTS[keyof typeof SUBSCRIPTION_EVENTS];
|
|
15
|
+
|
|
16
|
+
export interface SyncStatusChangedEvent {
|
|
17
|
+
status: 'syncing' | 'success' | 'error';
|
|
18
|
+
phase: 'purchase' | 'renewal';
|
|
19
|
+
userId?: string;
|
|
20
|
+
productId?: string;
|
|
21
|
+
error?: string;
|
|
22
|
+
}
|
|
@@ -7,11 +7,7 @@ import { UsePremiumResult } from './usePremium.types';
|
|
|
7
7
|
/**
|
|
8
8
|
* Facade hook that combines status, packages, and actions.
|
|
9
9
|
*
|
|
10
|
-
*
|
|
11
|
-
* components to use more focused hooks (usePremiumStatus, usePremiumPackages, usePremiumActions)
|
|
12
|
-
* for better performance and testability.
|
|
13
|
-
*
|
|
14
|
-
* For new components, consider using the focused hooks:
|
|
10
|
+
* Consider using the focused hooks for better performance:
|
|
15
11
|
* - usePremiumStatus() - when you only need premium status
|
|
16
12
|
* - usePremiumPackages() - when you only need package data
|
|
17
13
|
* - usePremiumActions() - when you only need actions
|
|
@@ -28,7 +24,6 @@ export const usePremium = (): UsePremiumResult => {
|
|
|
28
24
|
...status,
|
|
29
25
|
...packages,
|
|
30
26
|
...actions,
|
|
31
|
-
// Merge loading states for backward compatibility
|
|
32
27
|
isLoading: status.isSyncing || packages.isLoading || actions.isLoading,
|
|
33
28
|
}), [
|
|
34
29
|
status,
|
package/src/index.ts
CHANGED
|
@@ -9,6 +9,13 @@ export {
|
|
|
9
9
|
PURCHASE_TYPE,
|
|
10
10
|
ANONYMOUS_CACHE_KEY,
|
|
11
11
|
} from "./domains/subscription/core/SubscriptionConstants";
|
|
12
|
+
|
|
13
|
+
// Domain Events
|
|
14
|
+
export { SUBSCRIPTION_EVENTS } from "./domains/subscription/core/events/SubscriptionEvents";
|
|
15
|
+
export type { SubscriptionEventType, SyncStatusChangedEvent } from "./domains/subscription/core/events/SubscriptionEvents";
|
|
16
|
+
export type { PurchaseCompletedEvent, RenewalDetectedEvent, PremiumStatusChangedEvent } from "./domains/subscription/core/SubscriptionEvents";
|
|
17
|
+
export { FLOW_EVENTS } from "./domains/subscription/core/events/FlowEvents";
|
|
18
|
+
export type { FlowEventType, OnboardingCompletedEvent, PaywallShownEvent, PaywallClosedEvent } from "./domains/subscription/core/events/FlowEvents";
|
|
12
19
|
export type {
|
|
13
20
|
UserTierType,
|
|
14
21
|
SubscriptionStatusType,
|
|
@@ -176,10 +183,6 @@ export type { ManagedSubscriptionFlowProps } from "./domains/subscription/presen
|
|
|
176
183
|
export { SubscriptionFlowStatus } from "./domains/subscription/presentation/useSubscriptionFlow";
|
|
177
184
|
export { SubscriptionFlowProvider, useSubscriptionFlowStatus } from "./domains/subscription/presentation/providers/SubscriptionFlowProvider";
|
|
178
185
|
|
|
179
|
-
// Purchase Loading Overlay
|
|
180
|
-
export { PurchaseLoadingOverlay } from "./domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay";
|
|
181
|
-
export type { PurchaseLoadingOverlayProps } from "./domains/subscription/presentation/components/overlay/PurchaseLoadingOverlay";
|
|
182
|
-
|
|
183
186
|
// Init Module Factory
|
|
184
187
|
export {
|
|
185
188
|
createSubscriptionInitModule,
|
|
@@ -17,7 +17,7 @@ class SubscriptionEventBus {
|
|
|
17
17
|
if (!this.listeners.has(event)) {
|
|
18
18
|
this.listeners.set(event, new Set());
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
const eventSet = this.listeners.get(event)!;
|
|
22
22
|
eventSet.add(callback as EventCallback);
|
|
23
23
|
|
|
@@ -36,8 +36,6 @@ class SubscriptionEventBus {
|
|
|
36
36
|
const listeners = this.listeners.get(event);
|
|
37
37
|
if (!listeners || listeners.size === 0) return;
|
|
38
38
|
|
|
39
|
-
// Use microtask for async execution to not block main thread
|
|
40
|
-
// but keep it fast.
|
|
41
39
|
listeners.forEach(callback => {
|
|
42
40
|
queueMicrotask(() => {
|
|
43
41
|
try {
|
|
@@ -71,19 +69,9 @@ class SubscriptionEventBus {
|
|
|
71
69
|
|
|
72
70
|
export const subscriptionEventBus = SubscriptionEventBus.getInstance();
|
|
73
71
|
|
|
74
|
-
export
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
SYNC_STATUS_CHANGED: "sync_status_changed",
|
|
80
|
-
} as const;
|
|
81
|
-
|
|
82
|
-
export const FLOW_EVENTS = {
|
|
83
|
-
ONBOARDING_COMPLETED: "flow_onboarding_completed",
|
|
84
|
-
PAYWALL_SHOWN: "flow_paywall_shown",
|
|
85
|
-
PAYWALL_CLOSED: "flow_paywall_closed",
|
|
86
|
-
} as const;
|
|
72
|
+
// Re-export event constants for external use
|
|
73
|
+
export { SUBSCRIPTION_EVENTS } from "../../domains/subscription/core/events/SubscriptionEvents";
|
|
74
|
+
export { FLOW_EVENTS } from "../../domains/subscription/core/events/FlowEvents";
|
|
75
|
+
export type { SubscriptionEventType } from "../../domains/subscription/core/events/SubscriptionEvents";
|
|
76
|
+
export type { FlowEventType } from "../../domains/subscription/core/events/FlowEvents";
|
|
87
77
|
|
|
88
|
-
export type SubscriptionEventType = typeof SUBSCRIPTION_EVENTS[keyof typeof SUBSCRIPTION_EVENTS];
|
|
89
|
-
export type FlowEventType = typeof FLOW_EVENTS[keyof typeof FLOW_EVENTS];
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Purchase Loading Overlay
|
|
3
|
-
* Full-screen overlay shown during purchase operations
|
|
4
|
-
* Locks the UI and shows a spinner with optional message
|
|
5
|
-
*
|
|
6
|
-
* This is now a props-based component. Pass isLoading from parent component.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import React from "react";
|
|
10
|
-
import { View, Modal, StyleSheet } from "react-native";
|
|
11
|
-
import { AtomicSpinner, AtomicText } from "@umituz/react-native-design-system/atoms";
|
|
12
|
-
import { useAppDesignTokens } from "@umituz/react-native-design-system/theme";
|
|
13
|
-
import type { PurchaseLoadingOverlayProps } from "./PurchaseLoadingOverlay.types";
|
|
14
|
-
|
|
15
|
-
export type { PurchaseLoadingOverlayProps };
|
|
16
|
-
|
|
17
|
-
export const PurchaseLoadingOverlay: React.FC<PurchaseLoadingOverlayProps> = React.memo(
|
|
18
|
-
({ loadingText, isLoading }) => {
|
|
19
|
-
const tokens = useAppDesignTokens();
|
|
20
|
-
|
|
21
|
-
return (
|
|
22
|
-
<Modal visible={isLoading} transparent animationType="none" statusBarTranslucent>
|
|
23
|
-
<View style={[styles.container, { backgroundColor: "rgba(0, 0, 0, 0.7)" }]}>
|
|
24
|
-
<View style={[styles.content, { backgroundColor: tokens.colors.surface }]}>
|
|
25
|
-
<AtomicSpinner size="lg" color="primary" />
|
|
26
|
-
{loadingText && (
|
|
27
|
-
<AtomicText
|
|
28
|
-
type="bodyLarge"
|
|
29
|
-
style={[styles.text, { color: tokens.colors.textPrimary }]}
|
|
30
|
-
>
|
|
31
|
-
{loadingText}
|
|
32
|
-
</AtomicText>
|
|
33
|
-
)}
|
|
34
|
-
</View>
|
|
35
|
-
</View>
|
|
36
|
-
</Modal>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
);
|
|
40
|
-
|
|
41
|
-
PurchaseLoadingOverlay.displayName = "PurchaseLoadingOverlay";
|
|
42
|
-
|
|
43
|
-
const styles = StyleSheet.create({
|
|
44
|
-
container: {
|
|
45
|
-
flex: 1,
|
|
46
|
-
justifyContent: "center",
|
|
47
|
-
alignItems: "center",
|
|
48
|
-
},
|
|
49
|
-
content: {
|
|
50
|
-
paddingHorizontal: 32,
|
|
51
|
-
paddingVertical: 24,
|
|
52
|
-
borderRadius: 16,
|
|
53
|
-
alignItems: "center",
|
|
54
|
-
minWidth: 200,
|
|
55
|
-
},
|
|
56
|
-
text: {
|
|
57
|
-
marginTop: 16,
|
|
58
|
-
textAlign: "center",
|
|
59
|
-
},
|
|
60
|
-
});
|