@umituz/react-native-subscription 2.39.8 → 2.39.10

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.
Files changed (67) hide show
  1. package/package.json +1 -1
  2. package/src/domains/credits/application/CreditLimitCalculator.ts +6 -17
  3. package/src/domains/credits/core/UserCreditsDocument.ts +1 -1
  4. package/src/domains/credits/infrastructure/CreditsRepository.ts +3 -3
  5. package/src/domains/credits/infrastructure/operations/CreditsInitializer.ts +1 -1
  6. package/src/domains/credits/infrastructure/operations/CreditsWriter.ts +1 -1
  7. package/src/domains/paywall/components/PaywallFeatures.tsx +1 -1
  8. package/src/domains/paywall/components/PaywallFooter.tsx +1 -1
  9. package/src/domains/paywall/components/PaywallScreen.styles.ts +116 -44
  10. package/src/domains/paywall/components/PaywallScreen.tsx +184 -138
  11. package/src/domains/paywall/entities/types.ts +2 -0
  12. package/src/domains/paywall/hooks/usePaywallActions.ts +32 -40
  13. package/src/domains/paywall/utils/paywallLayoutUtils.ts +55 -0
  14. package/src/domains/revenuecat/core/types/RevenueCatData.ts +1 -1
  15. package/src/domains/revenuecat/core/types/RevenueCatTypes.ts +2 -2
  16. package/src/domains/revenuecat/infrastructure/services/RevenueCatInitializer.types.ts +1 -1
  17. package/src/domains/revenuecat/infrastructure/services/userSwitchHandler.ts +1 -1
  18. package/src/domains/subscription/application/SubscriptionInitializerTypes.ts +1 -1
  19. package/src/domains/subscription/application/SubscriptionSyncProcessor.ts +5 -22
  20. package/src/domains/subscription/application/SubscriptionSyncUtils.ts +1 -1
  21. package/src/domains/subscription/application/featureGate/featureGateBusinessRules.ts +27 -10
  22. package/src/domains/subscription/application/initializer/BackgroundInitializer.ts +42 -41
  23. package/src/domains/subscription/core/SubscriptionEvents.ts +1 -1
  24. package/src/domains/subscription/core/SubscriptionStatusHandlers.ts +1 -5
  25. package/src/domains/subscription/infrastructure/handlers/PackageHandler.ts +4 -6
  26. package/src/domains/subscription/infrastructure/handlers/PurchaseStatusResolver.ts +2 -2
  27. package/src/domains/subscription/infrastructure/handlers/package-operations/PackageRestorer.ts +1 -1
  28. package/src/domains/subscription/infrastructure/hooks/usePurchasePackage.ts +1 -1
  29. package/src/domains/subscription/infrastructure/hooks/useRestorePurchase.ts +1 -1
  30. package/src/domains/subscription/infrastructure/managers/SubscriptionManager.types.ts +2 -2
  31. package/src/domains/subscription/infrastructure/managers/initializationHandler.ts +1 -1
  32. package/src/domains/subscription/infrastructure/services/CustomerInfoListenerManager.ts +1 -1
  33. package/src/domains/subscription/infrastructure/services/PurchaseHandler.ts +2 -2
  34. package/src/domains/subscription/infrastructure/services/RestoreHandler.ts +4 -4
  35. package/src/domains/subscription/infrastructure/services/RevenueCatService.types.ts +1 -1
  36. package/src/domains/subscription/infrastructure/services/ServiceStateManager.ts +1 -1
  37. package/src/domains/subscription/infrastructure/services/listeners/CustomerInfoHandler.ts +4 -2
  38. package/src/domains/subscription/infrastructure/services/listeners/ListenerState.ts +1 -1
  39. package/src/domains/subscription/infrastructure/services/purchase/PurchaseErrorHandler.ts +3 -3
  40. package/src/domains/subscription/infrastructure/services/purchase/PurchaseExecutor.ts +2 -1
  41. package/src/domains/subscription/infrastructure/services/purchase/PurchaseValidator.ts +1 -1
  42. package/src/domains/subscription/infrastructure/services/revenueCatServiceInstance.ts +1 -1
  43. package/src/domains/subscription/infrastructure/utils/InitializationCache.ts +35 -42
  44. package/src/domains/subscription/infrastructure/utils/PremiumStatusSyncer.ts +3 -3
  45. package/src/domains/subscription/presentation/components/details/PremiumDetailsCardTypes.ts +1 -1
  46. package/src/domains/subscription/presentation/components/sections/SubscriptionSection.types.ts +1 -1
  47. package/src/domains/subscription/presentation/screens/SubscriptionDetailScreen.tsx +1 -1
  48. package/src/domains/subscription/presentation/screens/SubscriptionDetailScreen.types.ts +1 -1
  49. package/src/domains/subscription/presentation/stores/purchaseLoadingStore.ts +11 -8
  50. package/src/domains/subscription/presentation/useSubscriptionStatus.types.ts +1 -1
  51. package/src/domains/subscription/utils/featureGateUtils.ts +37 -0
  52. package/src/domains/subscription/utils/packageTypeFormatter.ts +1 -1
  53. package/src/domains/wallet/infrastructure/repositories/transaction/CollectionBuilder.ts +1 -1
  54. package/src/domains/wallet/infrastructure/repositories/transaction/TransactionFetcher.ts +2 -1
  55. package/src/domains/wallet/infrastructure/repositories/transaction/TransactionWriter.ts +2 -1
  56. package/src/domains/wallet/presentation/screens/WalletScreen.tsx +1 -1
  57. package/src/index.ts +5 -2
  58. package/src/init/createSubscriptionInitModule.ts +2 -1
  59. package/src/shared/infrastructure/SubscriptionEventBus.ts +24 -18
  60. package/src/domains/revenuecat/core/errors/index.ts +0 -3
  61. package/src/domains/revenuecat/core/types/index.ts +0 -3
  62. package/src/domains/subscription/application/initializer/index.ts +0 -2
  63. package/src/domains/subscription/core/types/index.ts +0 -3
  64. package/src/domains/subscription/infrastructure/handlers/package-operations/index.ts +0 -4
  65. package/src/domains/subscription/infrastructure/utils/renewal/index.ts +0 -3
  66. package/src/shared/infrastructure/firestore/index.ts +0 -2
  67. package/src/shared/presentation/index.ts +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@umituz/react-native-subscription",
3
- "version": "2.39.8",
3
+ "version": "2.39.10",
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,21 +1,10 @@
1
1
  import type { CreditsConfig } from "../core/Credits";
2
- import { detectPackageType } from "../../../utils/packageTypeDetector";
3
- import { getCreditAllocation } from "../../../utils/creditMapper";
2
+ import { calculateCreditLimit as calculateLimit } from "../utils/creditCalculations";
4
3
 
4
+ /**
5
+ * Service to calculate credit limits based on product configuration.
6
+ * Uses centralized utility functions for calculations.
7
+ */
5
8
  export function calculateCreditLimit(productId: string | undefined, config: CreditsConfig): number {
6
- if (!productId) {
7
- throw new Error("[CreditLimitCalculator] Cannot calculate credit limit without productId");
8
- }
9
-
10
- const explicitAmount = config.creditPackageAmounts?.[productId];
11
- if (explicitAmount !== undefined && explicitAmount !== null) return explicitAmount;
12
-
13
- const packageType = detectPackageType(productId);
14
- const dynamicLimit = getCreditAllocation(packageType, config.packageAllocations);
15
-
16
- if (dynamicLimit === null || dynamicLimit === undefined) {
17
- throw new Error(`[CreditLimitCalculator] Cannot determine credit limit for productId: ${productId}, packageType: ${packageType}`);
18
- }
19
-
20
- return dynamicLimit;
9
+ return calculateLimit(productId, config);
21
10
  }
@@ -5,7 +5,7 @@ import type {
5
5
  PackageType,
6
6
  Platform
7
7
  } from "../../subscription/core/SubscriptionConstants";
8
- import type { Store, OwnershipType } from "../../revenuecat/core/types";
8
+ import type { Store, OwnershipType } from "../../revenuecat/core/types/RevenueCatTypes";
9
9
 
10
10
  export type {
11
11
  PurchaseSource,
@@ -2,14 +2,14 @@ import type { Firestore, DocumentReference } from "@umituz/react-native-firebase
2
2
  import { BaseRepository } from "@umituz/react-native-firebase";
3
3
  import type { CreditsConfig, CreditsResult, DeductCreditsResult } from "../core/Credits";
4
4
  import type { PurchaseSource } from "../core/UserCreditsDocument";
5
- import type { RevenueCatData } from "../../revenuecat/core/types";
5
+ import type { RevenueCatData } from "../../revenuecat/core/types/RevenueCatData";
6
6
  import { deductCreditsOperation } from "../application/DeductCreditsCommand";
7
7
  import { refundCreditsOperation } from "../application/RefundCreditsCommand";
8
8
  import { PURCHASE_TYPE, type PurchaseType } from "../../subscription/core/SubscriptionConstants";
9
- import { requireFirestore, buildDocRef, type CollectionConfig } from "../../../shared/infrastructure/firestore";
9
+ import { requireFirestore, buildDocRef, type CollectionConfig } from "../../../shared/infrastructure/firestore/collectionUtils";
10
10
  import { fetchCredits, checkHasCredits, documentExists } from "./operations/CreditsFetcher";
11
11
  import { syncExpiredStatus, syncPremiumMetadata, createRecoveryCreditsDocument } from "./operations/CreditsWriter";
12
- import type { SubscriptionMetadata } from "../../subscription/core/types";
12
+ import type { SubscriptionMetadata } from "../../subscription/core/types/SubscriptionMetadata";
13
13
  import { initializeCreditsWithRetry } from "./operations/CreditsInitializer";
14
14
  import { calculateCreditLimit } from "../application/CreditLimitCalculator";
15
15
 
@@ -3,7 +3,7 @@ import type { CreditsConfig, CreditsResult } from "../../core/Credits";
3
3
  import type { PurchaseSource } from "../../core/UserCreditsDocument";
4
4
  import { initializeCreditsTransaction } from "../../application/CreditsInitializer";
5
5
  import { mapCreditsDocumentToEntity } from "../../core/CreditsMapper";
6
- import type { RevenueCatData } from "../../../revenuecat/core/types";
6
+ import type { RevenueCatData } from "../../../revenuecat/core/types/RevenueCatData";
7
7
  import { calculateCreditLimit } from "../../application/CreditLimitCalculator";
8
8
  import { PURCHASE_TYPE, type PurchaseType } from "../../../subscription/core/SubscriptionConstants";
9
9
 
@@ -3,7 +3,7 @@ import { runTransaction, serverTimestamp } from "@umituz/react-native-firebase";
3
3
  import { doc, getDoc, setDoc } from "firebase/firestore";
4
4
  import { SUBSCRIPTION_STATUS } from "../../../subscription/core/SubscriptionConstants";
5
5
  import { resolveSubscriptionStatus } from "../../../subscription/core/SubscriptionStatus";
6
- import type { SubscriptionMetadata } from "../../../subscription/core/types";
6
+ import type { SubscriptionMetadata } from "../../../subscription/core/types/SubscriptionMetadata";
7
7
  import { toTimestamp } from "../../../../shared/utils/dateConverter";
8
8
  import { isPast } from "../../../../utils/dateUtils";
9
9
  import { getAppVersion, validatePlatform } from "../../../../utils/appUtils";
@@ -10,7 +10,7 @@ export const PaywallFeatures: React.FC<{ features: SubscriptionFeature[] }> = ({
10
10
  if (!features.length) return null;
11
11
 
12
12
  return (
13
- <View style={[styles.features, { backgroundColor: tokens.colors.surfaceSecondary }]}>
13
+ <View style={[styles.featuresContainer, { backgroundColor: tokens.colors.surfaceSecondary }]}>
14
14
  {features.map((feature) => (
15
15
  <View key={`${feature.icon}-${feature.text}`} style={styles.featureRow}>
16
16
  <View style={[styles.featureIcon, { backgroundColor: tokens.colors.primary }]}>
@@ -25,7 +25,7 @@ export const PaywallFooter: React.FC<PaywallFooterProps> = ({
25
25
  return (
26
26
  <View style={styles.footer}>
27
27
  {onRestore && (
28
- <TouchableOpacity onPress={onRestore} disabled={isProcessing} style={[styles.restoreButton, isProcessing && styles.restoreButtonDisabled]}>
28
+ <TouchableOpacity onPress={onRestore} disabled={isProcessing} style={[styles.restoreButton, isProcessing && styles.ctaDisabled]}>
29
29
  <AtomicText type="bodySmall" style={[styles.footerLink, { color: tokens.colors.textSecondary }]}>
30
30
  {isProcessing ? translations.processingText : translations.restoreButtonText}
31
31
  </AtomicText>
@@ -1,97 +1,169 @@
1
- import { StyleSheet } from "react-native";
1
+ import { StyleSheet, Platform } from "react-native";
2
2
 
3
3
  export const paywallScreenStyles = StyleSheet.create({
4
4
  container: {
5
5
  flex: 1,
6
6
  },
7
+ // Header / Hero
7
8
  heroContainer: {
8
9
  alignItems: "center",
9
- marginBottom: 24,
10
+ justifyContent: "center",
11
+ marginVertical: 24,
12
+ height: 140,
10
13
  },
11
14
  heroImage: {
12
15
  width: 120,
13
16
  height: 120,
14
- borderRadius: 60,
17
+ borderRadius: 30, // More modern rounded corners
15
18
  },
16
19
  header: {
17
20
  paddingHorizontal: 24,
18
- marginBottom: 24,
21
+ marginBottom: 32,
22
+ alignItems: "center",
19
23
  },
20
24
  title: {
21
- marginBottom: 8,
25
+ marginBottom: 12,
26
+ textAlign: "center",
27
+ fontWeight: "800",
28
+ letterSpacing: -0.5,
22
29
  },
23
30
  subtitle: {
24
31
  lineHeight: 22,
32
+ textAlign: "center",
33
+ opacity: 0.8,
34
+ paddingHorizontal: 12,
25
35
  },
26
- plans: {
27
- paddingHorizontal: 16,
36
+
37
+ // Sections
38
+ sectionHeader: {
39
+ paddingHorizontal: 24,
40
+ marginTop: 24,
28
41
  marginBottom: 16,
29
42
  },
30
- loading: {
43
+ sectionTitle: {
44
+ fontWeight: "700",
45
+ textTransform: "uppercase",
46
+ letterSpacing: 1,
47
+ fontSize: 13,
48
+ opacity: 0.6,
49
+ },
50
+
51
+ // Features
52
+ featuresContainer: {
53
+ marginHorizontal: 24,
54
+ padding: 20,
55
+ borderRadius: 24,
56
+ gap: 16,
57
+ borderWidth: 1,
58
+ borderColor: "rgba(255, 255, 255, 0.1)",
59
+ },
60
+ featureRow: {
61
+ flexDirection: "row",
62
+ alignItems: "center",
63
+ gap: 14,
64
+ },
65
+ featureIcon: {
66
+ width: 30,
67
+ height: 30,
68
+ borderRadius: 10,
69
+ justifyContent: "center",
31
70
  alignItems: "center",
32
- paddingVertical: 32,
71
+ shadowColor: "#000",
72
+ shadowOffset: { width: 0, height: 2 },
73
+ shadowOpacity: 0.2,
74
+ shadowRadius: 4,
75
+ elevation: 3,
33
76
  },
34
- loadingText: {
35
- marginTop: 12,
77
+ featureText: {
78
+ flex: 1,
79
+ fontWeight: "500",
80
+ fontSize: 15,
36
81
  },
82
+
83
+ // Fixed Footer
37
84
  stickyFooter: {
38
85
  position: "absolute",
39
86
  bottom: 0,
40
87
  left: 0,
41
88
  right: 0,
42
- paddingHorizontal: 16,
43
- paddingTop: 12,
89
+ paddingHorizontal: 24,
90
+ paddingTop: 20,
44
91
  borderTopWidth: 1,
45
- borderTopColor: "rgba(255, 255, 255, 0.1)",
92
+ borderTopColor: "rgba(255, 255, 255, 0.08)",
93
+ ...Platform.select({
94
+ ios: {
95
+ shadowColor: "#000",
96
+ shadowOffset: { width: 0, height: -4 },
97
+ shadowOpacity: 0.1,
98
+ shadowRadius: 12,
99
+ },
100
+ android: {
101
+ elevation: 8,
102
+ },
103
+ }),
46
104
  },
47
105
  cta: {
48
- borderRadius: 14,
49
- paddingVertical: 16,
106
+ borderRadius: 18,
107
+ height: 60,
108
+ justifyContent: "center",
50
109
  alignItems: "center",
110
+ shadowColor: "#000",
111
+ shadowOffset: { width: 0, height: 4 },
112
+ shadowOpacity: 0.3,
113
+ shadowRadius: 8,
114
+ elevation: 6,
51
115
  },
52
116
  ctaDisabled: {
53
- opacity: 0.6,
117
+ opacity: 0.5,
54
118
  },
55
119
  ctaText: {
56
- fontWeight: "600",
57
- },
58
- features: {
59
- padding: 16,
60
- },
61
- featureRow: {
62
- flexDirection: "row",
63
- alignItems: "center",
64
- marginBottom: 12,
65
- },
66
- featureIcon: {
67
- width: 32,
68
- height: 32,
69
- borderRadius: 16,
70
- alignItems: "center",
71
- justifyContent: "center",
72
- marginRight: 12,
73
- },
74
- featureText: {
75
- flex: 1,
120
+ fontWeight: "700",
121
+ letterSpacing: 0.5,
76
122
  },
123
+
124
+ // Footer Links
77
125
  footer: {
78
- paddingHorizontal: 16,
79
- paddingBottom: 16,
126
+ marginTop: 16,
127
+ alignItems: "center",
128
+ gap: 12,
80
129
  },
81
130
  restoreButton: {
82
- paddingVertical: 8,
83
- },
84
- restoreButtonDisabled: {
85
- opacity: 0.5,
131
+ paddingVertical: 4,
86
132
  },
87
133
  footerLink: {
88
134
  fontSize: 12,
135
+ fontWeight: "500",
136
+ textDecorationLine: "underline",
137
+ opacity: 0.7,
89
138
  },
90
139
  legalRow: {
91
140
  flexDirection: "row",
92
141
  justifyContent: "center",
93
142
  alignItems: "center",
143
+ gap: 20,
144
+ marginBottom: 8,
145
+ },
146
+
147
+ // Close Button
148
+ closeBtn: {
149
+ width: 40,
150
+ height: 40,
151
+ borderRadius: 20,
152
+ justifyContent: "center",
153
+ alignItems: "center",
154
+ marginRight: 16,
94
155
  marginTop: 8,
95
- gap: 16,
156
+ borderWidth: 1,
157
+ borderColor: "rgba(255, 255, 255, 0.1)",
158
+ },
159
+
160
+ // List
161
+ listContent: {
162
+ paddingBottom: 40,
163
+ },
164
+ loadingContainer: {
165
+ flex: 1,
166
+ justifyContent: "center",
167
+ alignItems: "center",
96
168
  },
97
169
  });