@umituz/react-native-subscription 2.43.19 → 2.43.21

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.43.19",
3
+ "version": "2.43.21",
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,4 +1,4 @@
1
- import React, { useState, useEffect } from "react";
1
+ import React, { useState, useEffect, useCallback } from "react";
2
2
  import type { NavigationProp } from "@react-navigation/native";
3
3
  import type { ImageSourcePropType } from "react-native";
4
4
  import { SplashScreen, useSplashFlow } from "@umituz/react-native-design-system/molecules";
@@ -99,9 +99,26 @@ const ManagedSubscriptionFlowInner = React.memo<ManagedSubscriptionFlowProps>(({
99
99
  // Hooks for paywall (called at component level, not inside conditional render)
100
100
  const { isPremium, isSyncing, credits } = usePremiumStatus();
101
101
  const { packages } = usePremiumPackages();
102
- const { purchasePackage, restorePurchase } = usePremiumActions();
102
+ const { purchasePackage: originalPurchasePackage, restorePurchase } = usePremiumActions();
103
103
  const { closePostOnboardingPaywall } = useSubscriptionFlowStore();
104
104
 
105
+ // Track if purchase was successful to avoid showing feedback
106
+ const [purchaseSuccessful, setPurchaseSuccessful] = useState(false);
107
+
108
+ // Wrap purchasePackage to track success
109
+ const purchasePackage = useCallback(async (pkgId: string) => {
110
+ const result = await originalPurchasePackage(pkgId);
111
+ if (result?.success) {
112
+ setPurchaseSuccessful(true);
113
+ }
114
+ return result;
115
+ }, [originalPurchasePackage]);
116
+
117
+ // Wrap onClose to pass purchase status
118
+ const handleClose = useCallback(() => {
119
+ closePostOnboardingPaywall({ purchased: purchaseSuccessful });
120
+ }, [closePostOnboardingPaywall, purchaseSuccessful]);
121
+
105
122
  const [isNavReady, setIsNavReady] = useState(false);
106
123
 
107
124
  // Mark navigation tree as ready after splash and localization
@@ -208,7 +225,7 @@ const ManagedSubscriptionFlowInner = React.memo<ManagedSubscriptionFlowProps>(({
208
225
  isSyncing={isSyncing}
209
226
  onPurchase={purchasePackage}
210
227
  onRestore={restorePurchase}
211
- onClose={closePostOnboardingPaywall}
228
+ onClose={handleClose}
212
229
  />
213
230
  );
214
231
  }
@@ -11,24 +11,24 @@ export const feedbackOptionStyles = StyleSheet.create({
11
11
  marginRight: 12,
12
12
  },
13
13
  radioButton: {
14
- width: 22,
15
- height: 22,
16
- borderRadius: 11,
17
- borderWidth: 2,
14
+ width: 26,
15
+ height: 26,
16
+ borderRadius: 13,
17
+ borderWidth: 2.5,
18
18
  justifyContent: "center",
19
19
  alignItems: "center",
20
20
  },
21
21
  radioButtonInner: {
22
- width: 12,
23
- height: 12,
24
- borderRadius: 6,
22
+ width: 14,
23
+ height: 14,
24
+ borderRadius: 7,
25
25
  },
26
26
  inputContainer: {
27
27
  padding: 12,
28
28
  },
29
29
  textInput: {
30
- fontSize: 15,
31
- borderWidth: 1,
32
- borderColor: "#ccc",
30
+ fontSize: 16,
31
+ borderWidth: 1.5,
32
+ lineHeight: 22,
33
33
  },
34
34
  });
@@ -20,10 +20,11 @@ export const FeedbackOption: React.FC<FeedbackOptionProps> = React.memo(({
20
20
  const tokens = useAppDesignTokens();
21
21
 
22
22
  const containerStyle = {
23
- marginBottom: tokens.spacing.sm,
24
23
  backgroundColor: tokens.colors.surfaceSecondary,
25
24
  borderRadius: tokens.borderRadius.md,
26
25
  overflow: "hidden" as const,
26
+ borderWidth: 1,
27
+ borderColor: isSelected ? tokens.colors.primary : "transparent",
27
28
  };
28
29
 
29
30
  return (
@@ -141,21 +141,22 @@ PaywallFeedbackScreen.displayName = "PaywallFeedbackScreen";
141
141
 
142
142
  const createScreenStyles = (
143
143
  tokens: {
144
- colors: { backgroundPrimary: string; border: string };
145
- spacing: { xl: number; sm: number; md: number };
144
+ colors: { backgroundPrimary: string; border: string; onPrimary: string; textDisabled: string; surfaceSecondary: string; primary: string };
145
+ spacing: { xl: number; sm: number; md: number; lg: number };
146
146
  },
147
147
  _insets: { top: number; bottom: number }
148
148
  ) => ({
149
149
  container: {
150
150
  flex: 1,
151
+ opacity: 1,
151
152
  },
152
153
  closeBtn: {
153
154
  position: 'absolute' as const,
154
155
  top: 12,
155
156
  right: 12,
156
- width: 36,
157
- height: 36,
158
- borderRadius: 18,
157
+ width: 40,
158
+ height: 40,
159
+ borderRadius: 20,
159
160
  zIndex: 1000,
160
161
  justifyContent: 'center' as const,
161
162
  alignItems: 'center' as const,
@@ -164,21 +165,22 @@ const createScreenStyles = (
164
165
  flex: 1,
165
166
  },
166
167
  scrollContent: {
167
- paddingTop: 60,
168
- paddingBottom: 100,
168
+ paddingTop: 80,
169
+ paddingBottom: 120,
169
170
  },
170
171
  header: {
171
172
  paddingHorizontal: tokens.spacing.xl,
172
- marginBottom: tokens.spacing.xl,
173
+ marginBottom: tokens.spacing.xl + 8,
173
174
  },
174
175
  title: {
175
- marginBottom: tokens.spacing.sm,
176
+ marginBottom: tokens.spacing.md + 4,
176
177
  },
177
178
  subtitle: {
178
- lineHeight: 22,
179
+ lineHeight: 24,
179
180
  },
180
181
  optionsContainer: {
181
182
  paddingHorizontal: tokens.spacing.xl,
183
+ gap: tokens.spacing.md,
182
184
  },
183
185
  footer: {
184
186
  position: 'absolute' as const,
@@ -186,17 +188,26 @@ const createScreenStyles = (
186
188
  left: 0,
187
189
  right: 0,
188
190
  paddingHorizontal: tokens.spacing.xl,
189
- paddingTop: tokens.spacing.md,
191
+ paddingTop: tokens.spacing.lg,
192
+ paddingBottom: tokens.spacing.lg,
190
193
  backgroundColor: tokens.colors.backgroundPrimary,
191
194
  borderTopWidth: 1,
192
195
  borderTopColor: tokens.colors.border,
196
+ opacity: 1,
193
197
  },
194
198
  submitButton: {
195
- borderRadius: 14,
196
- paddingVertical: 16,
199
+ borderRadius: 16,
200
+ paddingVertical: 18,
197
201
  alignItems: 'center' as const,
202
+ shadowColor: "#000",
203
+ shadowOffset: { width: 0, height: 2 },
204
+ shadowOpacity: 0.1,
205
+ shadowRadius: 4,
206
+ elevation: 3,
198
207
  },
199
208
  submitText: {
200
- fontWeight: "600" as const,
209
+ fontWeight: "700" as const,
210
+ fontSize: 17,
211
+ letterSpacing: 0.3,
201
212
  },
202
213
  });
@@ -36,7 +36,7 @@ export interface SubscriptionFlowState {
36
36
 
37
37
  export interface SubscriptionFlowActions {
38
38
  completeOnboarding: () => Promise<void>;
39
- closePostOnboardingPaywall: () => Promise<void>;
39
+ closePostOnboardingPaywall: (params?: { purchased: boolean }) => Promise<void>;
40
40
  closeFeedback: () => void;
41
41
  setAuthModalOpen: (open: boolean) => void;
42
42
  markPaywallShown: () => Promise<void>;
@@ -79,14 +79,18 @@ export const useSubscriptionFlowStore = createStore<SubscriptionFlowState, Subsc
79
79
  });
80
80
  subscriptionEventBus.emit(FLOW_EVENTS.ONBOARDING_COMPLETED, { timestamp: Date.now() });
81
81
  },
82
- closePostOnboardingPaywall: async () => {
82
+ closePostOnboardingPaywall: async (params?: { purchased: boolean }) => {
83
+ const purchased = params?.purchased ?? false;
83
84
  set({
84
85
  showPostOnboardingPaywall: false,
85
86
  paywallShown: true,
86
87
  status: SubscriptionFlowStatus.READY,
87
- showFeedback: true, // Show feedback screen when paywall is closed
88
+ showFeedback: !purchased, // Only show feedback if NOT purchased
89
+ });
90
+ subscriptionEventBus.emit(FLOW_EVENTS.PAYWALL_CLOSED, {
91
+ timestamp: Date.now(),
92
+ purchased
88
93
  });
89
- subscriptionEventBus.emit(FLOW_EVENTS.PAYWALL_CLOSED, { timestamp: Date.now() });
90
94
  },
91
95
  closeFeedback: () => set({ showFeedback: false }),
92
96
  setAuthModalOpen: (open: boolean) => set({ isAuthModalOpen: open }),