@umituz/react-native-subscription 2.24.14 → 2.24.16
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/PaywallTabBar.tsx +0 -1
- package/src/presentation/components/feedback/PaywallFeedbackModal.tsx +4 -15
- package/src/presentation/hooks/useSubscriptionSettingsConfig.ts +2 -2
- package/src/presentation/hooks/useSubscriptionSettingsConfig.utils.ts +30 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@umituz/react-native-subscription",
|
|
3
|
-
"version": "2.24.
|
|
3
|
+
"version": "2.24.16",
|
|
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",
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"@types/react": "~19.1.10",
|
|
57
57
|
"@typescript-eslint/eslint-plugin": "^8.50.1",
|
|
58
58
|
"@typescript-eslint/parser": "^8.50.1",
|
|
59
|
-
"@umituz/react-native-auth": "
|
|
60
|
-
"@umituz/react-native-design-system": "^2.9.
|
|
59
|
+
"@umituz/react-native-auth": "^3.6.14",
|
|
60
|
+
"@umituz/react-native-design-system": "^2.9.35",
|
|
61
61
|
"@umituz/react-native-firebase": "*",
|
|
62
62
|
"@umituz/react-native-localization": "^3.6.0",
|
|
63
63
|
"eslint": "^9.39.2",
|
|
@@ -18,7 +18,6 @@ interface PaywallTabBarProps {
|
|
|
18
18
|
export const PaywallTabBar: React.FC<PaywallTabBarProps> = React.memo(
|
|
19
19
|
({ activeTab, onTabChange, creditsLabel, subscriptionLabel }) => {
|
|
20
20
|
const tokens = useAppDesignTokens();
|
|
21
|
-
const isCreditsActive = activeTab === "credits";
|
|
22
21
|
|
|
23
22
|
const renderTab = (tab: PaywallTabType, label: string) => {
|
|
24
23
|
const isActive = activeTab === tab;
|
|
@@ -4,14 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import React, { useMemo } from "react";
|
|
7
|
-
import {
|
|
8
|
-
View,
|
|
9
|
-
Modal,
|
|
10
|
-
TouchableOpacity,
|
|
11
|
-
Pressable,
|
|
12
|
-
TextInput,
|
|
13
|
-
KeyboardAvoidingView,
|
|
14
|
-
} from "react-native";
|
|
7
|
+
import { View, TouchableOpacity, TextInput } from "react-native";
|
|
15
8
|
import { AtomicText, BaseModal } from "@umituz/react-native-design-system";
|
|
16
9
|
import { useAppDesignTokens } from "@umituz/react-native-design-system";
|
|
17
10
|
import { useLocalization } from "@umituz/react-native-localization";
|
|
@@ -74,15 +67,11 @@ export const PaywallFeedbackModal: React.FC<PaywallFeedbackModalProps> = React.m
|
|
|
74
67
|
visible={visible}
|
|
75
68
|
onClose={handleSkip}
|
|
76
69
|
title={displayTitle}
|
|
77
|
-
|
|
70
|
+
subtitle={displaySubtitle}
|
|
78
71
|
>
|
|
79
|
-
<View style={{ paddingBottom: tokens.spacing.lg }}>
|
|
80
|
-
<AtomicText type="bodyMedium" style={[styles.subtitle, { marginBottom: tokens.spacing.md }]}>
|
|
81
|
-
{displaySubtitle}
|
|
82
|
-
</AtomicText>
|
|
83
|
-
|
|
72
|
+
<View style={{ paddingHorizontal: tokens.spacing.md, paddingBottom: tokens.spacing.lg }}>
|
|
84
73
|
<View style={[styles.optionsContainer, { backgroundColor: 'transparent', padding: 0 }]}>
|
|
85
|
-
{FEEDBACK_OPTION_IDS.map((optionId
|
|
74
|
+
{FEEDBACK_OPTION_IDS.map((optionId) => {
|
|
86
75
|
const isSelected = selectedReason === optionId;
|
|
87
76
|
const isOther = optionId === "other";
|
|
88
77
|
const showInput = isSelected && isOther;
|
|
@@ -65,10 +65,10 @@ export const useSubscriptionSettingsConfig = (
|
|
|
65
65
|
// Days remaining
|
|
66
66
|
const daysRemaining = useMemo(() => calculateDaysRemaining(expiresAtIso), [expiresAtIso]);
|
|
67
67
|
|
|
68
|
-
// Status type
|
|
68
|
+
// Status type: prioritize Firestore status, then derive from willRenew + expiration
|
|
69
69
|
const statusType: SubscriptionStatusType = credits?.status
|
|
70
70
|
? (credits.status as SubscriptionStatusType)
|
|
71
|
-
: getSubscriptionStatusType(isPremium);
|
|
71
|
+
: getSubscriptionStatusType(isPremium, willRenew, expiresAtIso);
|
|
72
72
|
|
|
73
73
|
const creditsArray = useCreditsArray(credits, dynamicCreditLimit, translations);
|
|
74
74
|
|
|
@@ -37,10 +37,36 @@ export function useCreditsArray(
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* Calculates subscription status type
|
|
40
|
+
* Calculates subscription status type based on premium and renewal status
|
|
41
|
+
* @param isPremium - Whether user has premium subscription
|
|
42
|
+
* @param willRenew - Whether subscription will auto-renew (false = canceled)
|
|
43
|
+
* @param expiresAt - Expiration date ISO string (null for lifetime)
|
|
41
44
|
*/
|
|
42
45
|
export function getSubscriptionStatusType(
|
|
43
|
-
isPremium: boolean
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
isPremium: boolean,
|
|
47
|
+
willRenew?: boolean,
|
|
48
|
+
expiresAt?: string | null
|
|
49
|
+
): "active" | "canceled" | "expired" | "none" {
|
|
50
|
+
if (!isPremium) {
|
|
51
|
+
return "none";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Lifetime subscription (no expiration) - always active
|
|
55
|
+
if (!expiresAt) {
|
|
56
|
+
return "active";
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Check if expired
|
|
60
|
+
const now = new Date();
|
|
61
|
+
const expDate = new Date(expiresAt);
|
|
62
|
+
if (expDate < now) {
|
|
63
|
+
return "expired";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Premium with willRenew=false means subscription is canceled but still active until expiration
|
|
67
|
+
if (willRenew === false) {
|
|
68
|
+
return "canceled";
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return "active";
|
|
46
72
|
}
|