@umituz/react-native-subscription 2.14.47 → 2.14.49
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 +3 -3
- package/src/domains/paywall/components/PaywallHeader.tsx +1 -0
- package/src/domains/paywall/components/PaywallModal.styles.ts +49 -0
- package/src/domains/paywall/components/PaywallModal.tsx +2 -37
- package/src/domains/wallet/domain/entities/CreditCost.ts +3 -3
- package/src/domains/wallet/infrastructure/repositories/TransactionRepository.ts +11 -20
- package/src/domains/wallet/presentation/components/BalanceCard.tsx +4 -3
- package/src/domains/wallet/presentation/components/TransactionItem.tsx +4 -3
- package/src/domains/wallet/presentation/components/TransactionList.tsx +7 -5
- package/src/domains/wallet/presentation/hooks/useWallet.ts +6 -4
- package/src/domains/wallet/presentation/screens/WalletScreen.tsx +11 -8
- package/src/infrastructure/repositories/CreditsRepository.ts +7 -42
- package/src/infrastructure/services/CreditsInitializer.ts +1 -52
- package/src/presentation/components/feedback/PaywallFeedbackModal.tsx +1 -0
- package/src/presentation/components/sections/SubscriptionSection.tsx +4 -3
- package/src/presentation/hooks/useCreditChecker.ts +3 -2
- package/src/presentation/hooks/useCredits.ts +4 -3
- package/src/presentation/hooks/usePremium.ts +4 -3
- package/src/presentation/hooks/useSubscriptionDetails.ts +3 -2
- package/src/presentation/hooks/useSubscriptionSettingsConfig.ts +4 -3
- package/src/presentation/screens/SubscriptionDetailScreen.tsx +3 -2
- package/src/presentation/screens/components/UpgradePrompt.tsx +4 -3
- package/src/revenuecat/infrastructure/services/CustomerInfoListenerManager.ts +60 -158
- package/src/revenuecat/infrastructure/services/OfferingsFetcher.ts +13 -29
- package/src/revenuecat/infrastructure/services/PurchaseHandler.ts +64 -88
- package/src/revenuecat/infrastructure/services/RestoreHandler.ts +32 -48
- package/src/revenuecat/infrastructure/services/RevenueCatInitializer.ts +90 -219
- package/src/revenuecat/infrastructure/services/RevenueCatService.ts +121 -126
- package/src/revenuecat/infrastructure/utils/InitializationCache.ts +25 -29
- package/src/revenuecat/infrastructure/utils/PremiumStatusSyncer.ts +52 -100
- package/src/revenuecat/infrastructure/utils/UserIdProvider.ts +17 -25
- package/src/revenuecat/presentation/hooks/usePaywallFlow.ts +9 -8
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.14.
|
|
3
|
+
"version": "2.14.49",
|
|
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",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"license": "MIT",
|
|
30
30
|
"repository": {
|
|
31
31
|
"type": "git",
|
|
32
|
-
"url": "https://github.com/umituz/react-native-subscription"
|
|
32
|
+
"url": "git+https://github.com/umituz/react-native-subscription.git"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@umituz/react-native-design-system": "latest",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"expo-constants": "~16.0.0",
|
|
64
64
|
"expo-image": "~3.0.0",
|
|
65
65
|
"expo-linear-gradient": "~15.0.0",
|
|
66
|
-
"firebase": "^
|
|
66
|
+
"firebase": "^11.0.0",
|
|
67
67
|
"react": "19.1.0",
|
|
68
68
|
"react-native": "0.81.5",
|
|
69
69
|
"react-native-purchases": "^7.0.0",
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PaywallModal Styles
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { StyleSheet } from "react-native";
|
|
6
|
+
|
|
7
|
+
export const paywallModalStyles = StyleSheet.create({
|
|
8
|
+
modalContent: { padding: 0, borderWidth: 0, overflow: "hidden" },
|
|
9
|
+
container: { flex: 1 },
|
|
10
|
+
closeBtn: {
|
|
11
|
+
position: "absolute",
|
|
12
|
+
top: 12,
|
|
13
|
+
right: 12,
|
|
14
|
+
width: 32,
|
|
15
|
+
height: 32,
|
|
16
|
+
borderRadius: 16,
|
|
17
|
+
justifyContent: "center",
|
|
18
|
+
alignItems: "center",
|
|
19
|
+
zIndex: 10,
|
|
20
|
+
},
|
|
21
|
+
scroll: { flexGrow: 1, padding: 16, paddingTop: 16, paddingBottom: 32 },
|
|
22
|
+
heroContainer: { alignItems: "center", marginBottom: 20, marginTop: 32 },
|
|
23
|
+
heroImage: { width: 180, height: 180, borderRadius: 90 },
|
|
24
|
+
header: { alignItems: "center", marginBottom: 12 },
|
|
25
|
+
title: { fontWeight: "700", textAlign: "center", marginBottom: 4 },
|
|
26
|
+
subtitle: { textAlign: "center" },
|
|
27
|
+
features: { borderRadius: 12, padding: 12, marginBottom: 12, gap: 8 },
|
|
28
|
+
featureRow: { flexDirection: "row", alignItems: "center" },
|
|
29
|
+
featureIcon: {
|
|
30
|
+
width: 32,
|
|
31
|
+
height: 32,
|
|
32
|
+
borderRadius: 16,
|
|
33
|
+
justifyContent: "center",
|
|
34
|
+
alignItems: "center",
|
|
35
|
+
marginRight: 8,
|
|
36
|
+
},
|
|
37
|
+
featureText: { flex: 1, fontWeight: "500" },
|
|
38
|
+
loading: { alignItems: "center", paddingVertical: 24 },
|
|
39
|
+
loadingText: { marginTop: 8 },
|
|
40
|
+
plans: { marginBottom: 12 },
|
|
41
|
+
cta: { borderRadius: 12, paddingVertical: 14, alignItems: "center", marginBottom: 12 },
|
|
42
|
+
ctaDisabled: { opacity: 0.5 },
|
|
43
|
+
ctaText: { fontWeight: "700" },
|
|
44
|
+
footer: { flexDirection: "column", alignItems: "center", gap: 8 },
|
|
45
|
+
restoreButton: { marginBottom: 8 },
|
|
46
|
+
restoreButtonDisabled: { opacity: 0.5 },
|
|
47
|
+
legalRow: { flexDirection: "row", justifyContent: "center", gap: 16 },
|
|
48
|
+
footerLink: {},
|
|
49
|
+
});
|
|
@@ -4,13 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useState, useCallback } from "react";
|
|
7
|
-
import { View, ScrollView,
|
|
7
|
+
import { View, ScrollView, TouchableOpacity, ActivityIndicator, Linking, type ImageSourcePropType } from "react-native";
|
|
8
8
|
import { BaseModal, useAppDesignTokens, AtomicText, AtomicIcon } from "@umituz/react-native-design-system";
|
|
9
9
|
import { Image } from "expo-image";
|
|
10
10
|
import type { PurchasesPackage } from "react-native-purchases";
|
|
11
11
|
import { PlanCard } from "./PlanCard";
|
|
12
12
|
import { CreditCard } from "./CreditCard";
|
|
13
13
|
import type { PaywallMode, CreditsPackage, SubscriptionFeature, PaywallTranslations, PaywallLegalUrls } from '../entities';
|
|
14
|
+
import { paywallModalStyles as styles } from "./PaywallModal.styles";
|
|
14
15
|
|
|
15
16
|
export interface PaywallModalProps {
|
|
16
17
|
visible: boolean;
|
|
@@ -60,15 +61,6 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
60
61
|
const showCredits = mode === "credits";
|
|
61
62
|
const showSubscription = mode === "subscription" || mode === "hybrid";
|
|
62
63
|
|
|
63
|
-
// Debug logging
|
|
64
|
-
if (__DEV__ && visible) {
|
|
65
|
-
console.log("[PaywallModal] Props:", {
|
|
66
|
-
hasHeroImage: !!heroImage,
|
|
67
|
-
heroImageType: typeof heroImage,
|
|
68
|
-
packagesCount: subscriptionPackages.length,
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
64
|
const handlePurchase = useCallback(async () => {
|
|
73
65
|
setIsProcessing(true);
|
|
74
66
|
try {
|
|
@@ -234,30 +226,3 @@ export const PaywallModal: React.FC<PaywallModalProps> = React.memo((props) => {
|
|
|
234
226
|
});
|
|
235
227
|
|
|
236
228
|
PaywallModal.displayName = "PaywallModal";
|
|
237
|
-
|
|
238
|
-
const styles = StyleSheet.create({
|
|
239
|
-
modalContent: { padding: 0, borderWidth: 0, overflow: "hidden" },
|
|
240
|
-
container: { flex: 1 },
|
|
241
|
-
closeBtn: { position: "absolute", top: 12, right: 12, width: 32, height: 32, borderRadius: 16, justifyContent: "center", alignItems: "center", zIndex: 10 },
|
|
242
|
-
scroll: { flexGrow: 1, padding: 16, paddingTop: 16, paddingBottom: 32 },
|
|
243
|
-
heroContainer: { alignItems: "center", marginBottom: 20, marginTop: 32 },
|
|
244
|
-
heroImage: { width: 180, height: 180, borderRadius: 90 },
|
|
245
|
-
header: { alignItems: "center", marginBottom: 12 },
|
|
246
|
-
title: { fontWeight: "700", textAlign: "center", marginBottom: 4 },
|
|
247
|
-
subtitle: { textAlign: "center" },
|
|
248
|
-
features: { borderRadius: 12, padding: 12, marginBottom: 12, gap: 8 },
|
|
249
|
-
featureRow: { flexDirection: "row", alignItems: "center" },
|
|
250
|
-
featureIcon: { width: 32, height: 32, borderRadius: 16, justifyContent: "center", alignItems: "center", marginRight: 8 },
|
|
251
|
-
featureText: { flex: 1, fontWeight: "500" },
|
|
252
|
-
loading: { alignItems: "center", paddingVertical: 24 },
|
|
253
|
-
loadingText: { marginTop: 8 },
|
|
254
|
-
plans: { marginBottom: 12 },
|
|
255
|
-
cta: { borderRadius: 12, paddingVertical: 14, alignItems: "center", marginBottom: 12 },
|
|
256
|
-
ctaDisabled: { opacity: 0.5 },
|
|
257
|
-
ctaText: { fontWeight: "700" },
|
|
258
|
-
footer: { flexDirection: "column", alignItems: "center", gap: 8 },
|
|
259
|
-
restoreButton: { marginBottom: 8 },
|
|
260
|
-
restoreButtonDisabled: { opacity: 0.5 },
|
|
261
|
-
legalRow: { flexDirection: "row", justifyContent: "center", gap: 16 },
|
|
262
|
-
footerLink: {},
|
|
263
|
-
});
|
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { AICreditCosts } from "../types/credit-cost.types";
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
import {
|
|
10
|
+
DEFAULT_AI_CREDIT_COSTS,
|
|
11
|
+
createCreditCostConfig,
|
|
12
12
|
} from "../types/credit-cost.types";
|
|
13
13
|
|
|
14
14
|
export interface CreditCostEntity {
|
|
@@ -5,16 +5,17 @@
|
|
|
5
5
|
* Generic repository for use across hundreds of apps.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
8
|
+
import {
|
|
9
|
+
collection,
|
|
10
|
+
getDocs,
|
|
11
|
+
addDoc,
|
|
12
|
+
query,
|
|
13
|
+
where,
|
|
14
|
+
orderBy,
|
|
15
|
+
limit as firestoreLimit,
|
|
16
|
+
serverTimestamp,
|
|
17
|
+
type Firestore,
|
|
18
|
+
type QueryConstraint,
|
|
18
19
|
} from "firebase/firestore";
|
|
19
20
|
import { BaseRepository, getFirestore } from "@umituz/react-native-firebase";
|
|
20
21
|
import type {
|
|
@@ -83,9 +84,6 @@ export class TransactionRepository extends BaseRepository {
|
|
|
83
84
|
|
|
84
85
|
return { success: true, data: transactions };
|
|
85
86
|
} catch (error) {
|
|
86
|
-
if (__DEV__) {
|
|
87
|
-
console.error("[TransactionRepository] Error:", error);
|
|
88
|
-
}
|
|
89
87
|
return {
|
|
90
88
|
success: false,
|
|
91
89
|
error: {
|
|
@@ -127,10 +125,6 @@ export class TransactionRepository extends BaseRepository {
|
|
|
127
125
|
|
|
128
126
|
const docRef = await addDoc(colRef, docData);
|
|
129
127
|
|
|
130
|
-
if (__DEV__) {
|
|
131
|
-
console.log("[TransactionRepository] Added:", docRef.id);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
128
|
return {
|
|
135
129
|
success: true,
|
|
136
130
|
data: {
|
|
@@ -143,9 +137,6 @@ export class TransactionRepository extends BaseRepository {
|
|
|
143
137
|
},
|
|
144
138
|
};
|
|
145
139
|
} catch (error) {
|
|
146
|
-
if (__DEV__) {
|
|
147
|
-
console.error("[TransactionRepository] Add error:", error);
|
|
148
|
-
}
|
|
149
140
|
return {
|
|
150
141
|
success: false,
|
|
151
142
|
error: {
|
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
import { View, StyleSheet } from "react-native";
|
|
10
10
|
import { LinearGradient } from "expo-linear-gradient";
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
import {
|
|
12
|
+
useAppDesignTokens,
|
|
13
|
+
AtomicText,
|
|
14
|
+
AtomicIcon,
|
|
14
15
|
} from "@umituz/react-native-design-system";
|
|
15
16
|
|
|
16
17
|
export interface BalanceCardTranslations {
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
|
|
8
8
|
import React, { useMemo } from "react";
|
|
9
9
|
import { View, StyleSheet } from "react-native";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
useAppDesignTokens,
|
|
12
|
+
AtomicText,
|
|
13
|
+
AtomicIcon,
|
|
13
14
|
} from "@umituz/react-native-design-system";
|
|
14
15
|
import type { CreditLog, TransactionReason } from "../../domain/types/transaction.types";
|
|
15
16
|
|
|
@@ -7,13 +7,15 @@
|
|
|
7
7
|
|
|
8
8
|
import React from "react";
|
|
9
9
|
import { View, StyleSheet, ScrollView, ActivityIndicator } from "react-native";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
useAppDesignTokens,
|
|
12
|
+
AtomicText,
|
|
13
|
+
AtomicIcon,
|
|
13
14
|
} from "@umituz/react-native-design-system";
|
|
14
15
|
import type { CreditLog } from "../../domain/types/transaction.types";
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
import {
|
|
17
|
+
TransactionItem,
|
|
18
|
+
type TransactionItemTranslations,
|
|
17
19
|
} from "./TransactionItem";
|
|
18
20
|
|
|
19
21
|
export interface TransactionListTranslations extends TransactionItemTranslations {
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { useCallback, useMemo } from "react";
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
useCredits,
|
|
11
|
+
type UseCreditsParams,
|
|
11
12
|
} from "../../../../presentation/hooks/useCredits";
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
import {
|
|
14
|
+
useTransactionHistory,
|
|
15
|
+
type UseTransactionHistoryParams,
|
|
14
16
|
} from "./useTransactionHistory";
|
|
15
17
|
import type { CreditLog } from "../../domain/types/transaction.types";
|
|
16
18
|
|
|
@@ -9,16 +9,19 @@
|
|
|
9
9
|
import React from "react";
|
|
10
10
|
import { View, StyleSheet, ActivityIndicator, TouchableOpacity } from "react-native";
|
|
11
11
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
import {
|
|
13
|
+
useAppDesignTokens,
|
|
14
|
+
AtomicText,
|
|
15
|
+
AtomicIcon,
|
|
16
|
+
ScreenLayout,
|
|
16
17
|
} from "@umituz/react-native-design-system";
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
import {
|
|
19
|
+
BalanceCard,
|
|
20
|
+
type BalanceCardTranslations,
|
|
19
21
|
} from "../components/BalanceCard";
|
|
20
|
-
|
|
21
|
-
|
|
22
|
+
import {
|
|
23
|
+
TransactionList,
|
|
24
|
+
type TransactionListTranslations,
|
|
22
25
|
} from "../components/TransactionList";
|
|
23
26
|
import type { CreditLog } from "../../domain/types/transaction.types";
|
|
24
27
|
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
|
|
2
1
|
/**
|
|
3
2
|
* Credits Repository
|
|
4
3
|
*
|
|
@@ -6,12 +5,13 @@
|
|
|
6
5
|
* Extends BaseRepository from @umituz/react-native-firebase.
|
|
7
6
|
*/
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
8
|
+
import {
|
|
9
|
+
doc,
|
|
10
|
+
getDoc,
|
|
11
|
+
runTransaction,
|
|
12
|
+
serverTimestamp,
|
|
13
|
+
type Firestore,
|
|
14
|
+
type Transaction,
|
|
15
15
|
} from "firebase/firestore";
|
|
16
16
|
import { BaseRepository, getFirestore } from "@umituz/react-native-firebase";
|
|
17
17
|
import type {
|
|
@@ -91,14 +91,6 @@ export class CreditsRepository extends BaseRepository {
|
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
if (__DEV__) {
|
|
95
|
-
console.log("[CreditsRepository] Initialize credits:", {
|
|
96
|
-
userId,
|
|
97
|
-
purchaseId,
|
|
98
|
-
productId,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
|
|
102
94
|
try {
|
|
103
95
|
const creditsRef = this.getCreditsDocRef(db, userId);
|
|
104
96
|
|
|
@@ -110,27 +102,11 @@ export class CreditsRepository extends BaseRepository {
|
|
|
110
102
|
const allocation = getCreditAllocation(packageType);
|
|
111
103
|
|
|
112
104
|
if (allocation) {
|
|
113
|
-
// Override config with tier-specific credit amounts
|
|
114
105
|
configToUse = {
|
|
115
106
|
...this.config,
|
|
116
107
|
imageCreditLimit: allocation.imageCredits,
|
|
117
108
|
textCreditLimit: allocation.textCredits,
|
|
118
109
|
};
|
|
119
|
-
|
|
120
|
-
if (__DEV__) {
|
|
121
|
-
console.log("[CreditsRepository] Using tier-based allocation:", {
|
|
122
|
-
packageType,
|
|
123
|
-
imageCredits: allocation.imageCredits,
|
|
124
|
-
textCredits: allocation.textCredits,
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
128
|
-
if (__DEV__) {
|
|
129
|
-
console.warn(
|
|
130
|
-
"[CreditsRepository] Could not determine package type, using default config:",
|
|
131
|
-
this.config
|
|
132
|
-
);
|
|
133
|
-
}
|
|
134
110
|
}
|
|
135
111
|
}
|
|
136
112
|
|
|
@@ -141,13 +117,6 @@ export class CreditsRepository extends BaseRepository {
|
|
|
141
117
|
purchaseId
|
|
142
118
|
);
|
|
143
119
|
|
|
144
|
-
if (__DEV__) {
|
|
145
|
-
console.log("[CreditsRepository] Credits initialized successfully:", {
|
|
146
|
-
imageCredits: result.imageCredits,
|
|
147
|
-
textCredits: result.textCredits,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
|
|
151
120
|
return {
|
|
152
121
|
success: true,
|
|
153
122
|
data: {
|
|
@@ -158,10 +127,6 @@ export class CreditsRepository extends BaseRepository {
|
|
|
158
127
|
},
|
|
159
128
|
};
|
|
160
129
|
} catch (error) {
|
|
161
|
-
if (__DEV__) {
|
|
162
|
-
console.error("[CreditsRepository] Failed to initialize credits:", error);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
130
|
return {
|
|
166
131
|
success: false,
|
|
167
132
|
error: {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
2
|
runTransaction,
|
|
3
3
|
serverTimestamp,
|
|
4
4
|
type Firestore,
|
|
@@ -20,14 +20,6 @@ export async function initializeCreditsTransaction(
|
|
|
20
20
|
config: CreditsConfig,
|
|
21
21
|
purchaseId?: string
|
|
22
22
|
): Promise<InitializationResult> {
|
|
23
|
-
if (__DEV__) {
|
|
24
|
-
console.log("[CreditsInitializer] Starting transaction with config:", {
|
|
25
|
-
textCreditLimit: config.textCreditLimit,
|
|
26
|
-
imageCreditLimit: config.imageCreditLimit,
|
|
27
|
-
purchaseId,
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
|
|
31
23
|
return runTransaction(db, async (transaction: Transaction) => {
|
|
32
24
|
const creditsDoc = await transaction.get(creditsRef);
|
|
33
25
|
const now = serverTimestamp();
|
|
@@ -41,21 +33,7 @@ export async function initializeCreditsTransaction(
|
|
|
41
33
|
const existing = creditsDoc.data() as UserCreditsDocumentRead;
|
|
42
34
|
processedPurchases = existing.processedPurchases || [];
|
|
43
35
|
|
|
44
|
-
if (__DEV__) {
|
|
45
|
-
console.log("[CreditsInitializer] Existing credits found:", {
|
|
46
|
-
textCredits: existing.textCredits,
|
|
47
|
-
imageCredits: existing.imageCredits,
|
|
48
|
-
processedPurchases,
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
36
|
if (purchaseId && processedPurchases.includes(purchaseId)) {
|
|
53
|
-
if (__DEV__) {
|
|
54
|
-
console.warn(
|
|
55
|
-
"[CreditsInitializer] Purchase already processed:",
|
|
56
|
-
purchaseId
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
37
|
return {
|
|
60
38
|
textCredits: existing.textCredits,
|
|
61
39
|
imageCredits: existing.imageCredits,
|
|
@@ -66,31 +44,9 @@ export async function initializeCreditsTransaction(
|
|
|
66
44
|
newTextCredits = (existing.textCredits || 0) + config.textCreditLimit;
|
|
67
45
|
newImageCredits = (existing.imageCredits || 0) + config.imageCreditLimit;
|
|
68
46
|
|
|
69
|
-
if (__DEV__) {
|
|
70
|
-
console.log("[CreditsInitializer] Adding to existing credits:", {
|
|
71
|
-
existingText: existing.textCredits || 0,
|
|
72
|
-
existingImage: existing.imageCredits || 0,
|
|
73
|
-
adding: {
|
|
74
|
-
text: config.textCreditLimit,
|
|
75
|
-
image: config.imageCreditLimit,
|
|
76
|
-
},
|
|
77
|
-
newTotal: {
|
|
78
|
-
text: newTextCredits,
|
|
79
|
-
image: newImageCredits,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
|
|
84
47
|
if (existing.purchasedAt) {
|
|
85
48
|
purchasedAt = existing.purchasedAt as unknown as FieldValue;
|
|
86
49
|
}
|
|
87
|
-
} else {
|
|
88
|
-
if (__DEV__) {
|
|
89
|
-
console.log("[CreditsInitializer] Creating new credits document:", {
|
|
90
|
-
textCredits: newTextCredits,
|
|
91
|
-
imageCredits: newImageCredits,
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
50
|
}
|
|
95
51
|
|
|
96
52
|
if (purchaseId) {
|
|
@@ -106,13 +62,6 @@ export async function initializeCreditsTransaction(
|
|
|
106
62
|
processedPurchases,
|
|
107
63
|
});
|
|
108
64
|
|
|
109
|
-
if (__DEV__) {
|
|
110
|
-
console.log("[CreditsInitializer] Transaction completed successfully:", {
|
|
111
|
-
textCredits: newTextCredits,
|
|
112
|
-
imageCredits: newImageCredits,
|
|
113
|
-
});
|
|
114
|
-
}
|
|
115
|
-
|
|
116
65
|
return { textCredits: newTextCredits, imageCredits: newImageCredits };
|
|
117
66
|
});
|
|
118
67
|
}
|
|
@@ -7,9 +7,10 @@
|
|
|
7
7
|
import React from "react";
|
|
8
8
|
import { View, TouchableOpacity } from "react-native";
|
|
9
9
|
import type { StyleProp, ViewStyle } from "react-native";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
import {
|
|
11
|
+
PremiumDetailsCard,
|
|
12
|
+
type CreditInfo,
|
|
13
|
+
type PremiumDetailsTranslations,
|
|
13
14
|
} from "../details/PremiumDetailsCard";
|
|
14
15
|
import type { SubscriptionStatusType } from "../details/PremiumStatusBadge";
|
|
15
16
|
|
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
import { useMemo } from "react";
|
|
8
8
|
import type { CreditType } from "../../domain/entities/Credits";
|
|
9
9
|
import { getCreditsRepository } from "../../infrastructure/repositories/CreditsRepositoryProvider";
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
import {
|
|
11
|
+
createCreditChecker,
|
|
12
|
+
type CreditCheckResult,
|
|
12
13
|
} from "../../utils/creditChecker";
|
|
13
14
|
|
|
14
15
|
export interface UseCreditCheckerParams {
|
|
@@ -10,9 +10,10 @@ import { useCallback, useMemo } from "react";
|
|
|
10
10
|
import type { UserCredits, CreditType } from "../../domain/entities/Credits";
|
|
11
11
|
|
|
12
12
|
declare const __DEV__: boolean;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
getCreditsRepository,
|
|
15
|
+
getCreditsConfig,
|
|
16
|
+
isCreditsRepositoryConfigured,
|
|
16
17
|
} from "../../infrastructure/repositories/CreditsRepositoryProvider";
|
|
17
18
|
|
|
18
19
|
export const creditsQueryKeys = {
|
|
@@ -12,9 +12,10 @@ import type { PurchasesPackage } from 'react-native-purchases';
|
|
|
12
12
|
import type { UserCredits } from '../../domain/entities/Credits';
|
|
13
13
|
import { useCredits } from './useCredits';
|
|
14
14
|
import { useSubscriptionStatus } from './useSubscriptionStatus';
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
import {
|
|
16
|
+
useSubscriptionPackages,
|
|
17
|
+
usePurchasePackage,
|
|
18
|
+
useRestorePurchase,
|
|
18
19
|
} from '../../revenuecat/presentation/hooks/useSubscriptionQueries';
|
|
19
20
|
import { usePaywallVisibility } from './usePaywallVisibility';
|
|
20
21
|
|
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
|
|
6
6
|
import { useMemo } from "react";
|
|
7
7
|
import type { SubscriptionStatus } from "../../domain/entities/SubscriptionStatus";
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import {
|
|
9
|
+
getDaysUntilExpiration,
|
|
10
|
+
isSubscriptionExpired,
|
|
10
11
|
} from "../../utils/dateValidationUtils";
|
|
11
12
|
|
|
12
13
|
export interface SubscriptionDetails {
|
|
@@ -10,9 +10,10 @@ import { useSubscriptionStatus } from "./useSubscriptionStatus";
|
|
|
10
10
|
import { useCustomerInfo } from "../../revenuecat/presentation/hooks/useCustomerInfo";
|
|
11
11
|
import { usePaywallVisibility } from "./usePaywallVisibility";
|
|
12
12
|
import { SubscriptionManager } from "../../revenuecat/infrastructure/managers/SubscriptionManager";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
import {
|
|
14
|
+
convertPurchasedAt,
|
|
15
|
+
formatDateForLocale,
|
|
16
|
+
calculateDaysRemaining,
|
|
16
17
|
} from "../utils/subscriptionDateUtils";
|
|
17
18
|
import type {
|
|
18
19
|
SubscriptionSettingsConfig,
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
|
|
7
7
|
import React, { useMemo } from "react";
|
|
8
8
|
import { StyleSheet, View } from "react-native";
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
import {
|
|
10
|
+
useAppDesignTokens,
|
|
11
|
+
ScreenLayout,
|
|
11
12
|
} from "@umituz/react-native-design-system";
|
|
12
13
|
import { SubscriptionHeader } from "./components/SubscriptionHeader";
|
|
13
14
|
import { CreditsList } from "./components/CreditsList";
|
|
@@ -5,9 +5,10 @@
|
|
|
5
5
|
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
7
|
import { View, StyleSheet, TouchableOpacity } from "react-native";
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
import {
|
|
9
|
+
useAppDesignTokens,
|
|
10
|
+
AtomicText,
|
|
11
|
+
AtomicIcon,
|
|
11
12
|
} from "@umituz/react-native-design-system";
|
|
12
13
|
import type { UpgradePromptProps } from "../../types/SubscriptionDetailTypes";
|
|
13
14
|
|