@zezosoft/zezo-ott-react-native-ui-kit 1.0.8 → 1.0.9

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 (106) hide show
  1. package/README.md +1 -1
  2. package/lib/module/components/Account/Account.js +1 -1
  3. package/lib/module/components/Account/Account.js.map +1 -1
  4. package/lib/module/components/Auth/AuthProvider/AuthProvider.js +48 -19
  5. package/lib/module/components/Auth/AuthProvider/AuthProvider.js.map +1 -1
  6. package/lib/module/components/Auth/Login/LoginWithEmail.js +4 -2
  7. package/lib/module/components/Auth/Login/LoginWithEmail.js.map +1 -1
  8. package/lib/module/components/Auth/OTP/OTP.js +15 -1
  9. package/lib/module/components/Auth/OTP/OTP.js.map +1 -1
  10. package/lib/module/components/Auth/SignUp/SignUp.js +4 -2
  11. package/lib/module/components/Auth/SignUp/SignUp.js.map +1 -1
  12. package/lib/module/components/BlurView/BlurView.js +171 -0
  13. package/lib/module/components/BlurView/BlurView.js.map +1 -0
  14. package/lib/module/components/BlurView/index.js +9 -0
  15. package/lib/module/components/BlurView/index.js.map +1 -0
  16. package/lib/module/components/Content/Card/Styles/Four.js +1 -1
  17. package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
  18. package/lib/module/components/Content/Content.js +4 -2
  19. package/lib/module/components/Content/Content.js.map +1 -1
  20. package/lib/module/components/ContentView/ContentView.js +4 -2
  21. package/lib/module/components/ContentView/ContentView.js.map +1 -1
  22. package/lib/module/components/ContentView/components/MiniInfo.js +64 -19
  23. package/lib/module/components/ContentView/components/MiniInfo.js.map +1 -1
  24. package/lib/module/components/Settings/AppSettings.js +1 -1
  25. package/lib/module/components/Settings/AppSettings.js.map +1 -1
  26. package/lib/module/components/Subscription/SubOne.js +340 -13
  27. package/lib/module/components/Subscription/SubOne.js.map +1 -1
  28. package/lib/module/components/TabBar/One.js +71 -108
  29. package/lib/module/components/TabBar/One.js.map +1 -1
  30. package/lib/module/components/TabBar/Three.js +63 -78
  31. package/lib/module/components/TabBar/Three.js.map +1 -1
  32. package/lib/module/components/TabBar/Two.js +110 -106
  33. package/lib/module/components/TabBar/Two.js.map +1 -1
  34. package/lib/module/components/User/PurchaseHistory/PurchaseHistory.js +324 -0
  35. package/lib/module/components/User/PurchaseHistory/PurchaseHistory.js.map +1 -0
  36. package/lib/module/components/User/index.js +2 -1
  37. package/lib/module/components/User/index.js.map +1 -1
  38. package/lib/module/components/index.js +1 -0
  39. package/lib/module/components/index.js.map +1 -1
  40. package/lib/module/hooks/useNavigationMode.js +34 -0
  41. package/lib/module/hooks/useNavigationMode.js.map +1 -0
  42. package/lib/module/utils/Spacing.js +26 -0
  43. package/lib/module/utils/Spacing.js.map +1 -0
  44. package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts +1 -0
  45. package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts.map +1 -1
  46. package/lib/typescript/src/components/Auth/Login/LoginWithEmail.d.ts.map +1 -1
  47. package/lib/typescript/src/components/Auth/OTP/OTP.d.ts +2 -0
  48. package/lib/typescript/src/components/Auth/OTP/OTP.d.ts.map +1 -1
  49. package/lib/typescript/src/components/Auth/SignUp/SignUp.d.ts.map +1 -1
  50. package/lib/typescript/src/components/Auth/index.d.ts +2 -0
  51. package/lib/typescript/src/components/Auth/index.d.ts.map +1 -1
  52. package/lib/typescript/src/components/BlurView/BlurView.d.ts +48 -0
  53. package/lib/typescript/src/components/BlurView/BlurView.d.ts.map +1 -0
  54. package/lib/typescript/src/components/BlurView/index.d.ts +7 -0
  55. package/lib/typescript/src/components/BlurView/index.d.ts.map +1 -0
  56. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
  57. package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
  58. package/lib/typescript/src/components/ContentView/ContentView.d.ts +1 -1
  59. package/lib/typescript/src/components/ContentView/ContentView.d.ts.map +1 -1
  60. package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts +17 -1
  61. package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts.map +1 -1
  62. package/lib/typescript/src/components/Subscription/SubOne.d.ts +6 -0
  63. package/lib/typescript/src/components/Subscription/SubOne.d.ts.map +1 -1
  64. package/lib/typescript/src/components/Subscription/index.d.ts.map +1 -1
  65. package/lib/typescript/src/components/TabBar/One.d.ts +2 -2
  66. package/lib/typescript/src/components/TabBar/One.d.ts.map +1 -1
  67. package/lib/typescript/src/components/TabBar/Three.d.ts +3 -2
  68. package/lib/typescript/src/components/TabBar/Three.d.ts.map +1 -1
  69. package/lib/typescript/src/components/TabBar/Two.d.ts +13 -4
  70. package/lib/typescript/src/components/TabBar/Two.d.ts.map +1 -1
  71. package/lib/typescript/src/components/TabBar/index.d.ts +1 -1
  72. package/lib/typescript/src/components/User/PurchaseHistory/PurchaseHistory.d.ts +50 -0
  73. package/lib/typescript/src/components/User/PurchaseHistory/PurchaseHistory.d.ts.map +1 -0
  74. package/lib/typescript/src/components/User/index.d.ts +2 -1
  75. package/lib/typescript/src/components/User/index.d.ts.map +1 -1
  76. package/lib/typescript/src/components/index.d.ts +1 -0
  77. package/lib/typescript/src/components/index.d.ts.map +1 -1
  78. package/lib/typescript/src/hooks/useNavigationMode.d.ts +14 -0
  79. package/lib/typescript/src/hooks/useNavigationMode.d.ts.map +1 -0
  80. package/lib/typescript/src/types/content/content-view.types.d.ts +2 -0
  81. package/lib/typescript/src/types/content/content-view.types.d.ts.map +1 -1
  82. package/lib/typescript/src/utils/Spacing.d.ts +16 -0
  83. package/lib/typescript/src/utils/Spacing.d.ts.map +1 -0
  84. package/package.json +9 -5
  85. package/src/components/Account/Account.tsx +1 -1
  86. package/src/components/Auth/AuthProvider/AuthProvider.tsx +82 -37
  87. package/src/components/Auth/Login/LoginWithEmail.tsx +9 -2
  88. package/src/components/Auth/OTP/OTP.tsx +37 -1
  89. package/src/components/Auth/SignUp/SignUp.tsx +9 -2
  90. package/src/components/BlurView/BlurView.tsx +199 -0
  91. package/src/components/BlurView/index.ts +7 -0
  92. package/src/components/Content/Card/Styles/Four.tsx +3 -1
  93. package/src/components/Content/Content.tsx +5 -4
  94. package/src/components/ContentView/ContentView.tsx +8 -1
  95. package/src/components/ContentView/components/MiniInfo.tsx +99 -22
  96. package/src/components/Settings/AppSettings.tsx +1 -1
  97. package/src/components/Subscription/SubOne.tsx +422 -11
  98. package/src/components/TabBar/One.tsx +79 -141
  99. package/src/components/TabBar/Three.tsx +84 -99
  100. package/src/components/TabBar/Two.tsx +139 -110
  101. package/src/components/User/PurchaseHistory/PurchaseHistory.tsx +439 -0
  102. package/src/components/User/index.ts +8 -1
  103. package/src/components/index.ts +1 -0
  104. package/src/hooks/useNavigationMode.ts +35 -0
  105. package/src/types/content/content-view.types.ts +5 -0
  106. package/src/utils/Spacing.ts +27 -0
@@ -0,0 +1,439 @@
1
+ /**
2
+ * @author Naresh Dhamu
3
+ * @lastModified Mon 10 Nov 2025 at 03:35 PM
4
+ */
5
+
6
+ import React from 'react';
7
+ import {
8
+ StyleSheet,
9
+ View,
10
+ TouchableOpacity,
11
+ type StyleProp,
12
+ type ViewStyle,
13
+ type ListRenderItem,
14
+ } from 'react-native';
15
+ import { FlatGrid } from 'react-native-super-grid';
16
+ import { scale } from 'react-native-size-matters';
17
+ import LinearGradient from 'react-native-linear-gradient';
18
+ import { Search, Calendar, CheckCircle2, XCircle } from 'lucide-react-native';
19
+ import moment from 'moment';
20
+ import { useInternalTheme } from '../../../theme/hook/useInternalTheme';
21
+
22
+ import AppHeader from '../../Headers/AppHeader';
23
+ import { Text } from '../../Text';
24
+ import CardPoster from '../../Content/Card/components/CardPoster';
25
+ import type { IContentData } from '../../../types';
26
+ import type { ThemeOverride } from '../../../theme/themes';
27
+ import { RFValue } from 'react-native-responsive-fontsize';
28
+
29
+ export interface IPurchaseHistoryItem {
30
+ _id: string;
31
+ content_id: IContentData;
32
+ user_id: string;
33
+ status: 'valid' | 'expired' | string;
34
+ valid_upto: string;
35
+ price: number;
36
+ tvod_type: 'BUY' | 'RENT';
37
+ content_owner: string;
38
+ createdAt: string;
39
+ updatedAt: string;
40
+ __v: number;
41
+ }
42
+
43
+ export interface PurchaseHistoryProps {
44
+ data: IPurchaseHistoryItem[];
45
+ isLoading?: boolean;
46
+
47
+ // Header Config
48
+ title?: string;
49
+ headerComponent?: React.ReactNode;
50
+ onBackPress?: () => void;
51
+ onSearchPress?: () => void;
52
+ showSearchIcon?: boolean;
53
+
54
+ // Grid & Layout Customization
55
+ itemDimension?: number;
56
+ spacing?: number;
57
+ listStyle?: StyleProp<ViewStyle>;
58
+ contentContainerStyle?: StyleProp<ViewStyle>;
59
+
60
+ // Theme
61
+ theme?: ThemeOverride;
62
+
63
+ // Rendering Overrides
64
+ renderItem?: (
65
+ item: IPurchaseHistoryItem,
66
+ index: number
67
+ ) => React.ReactElement | null;
68
+ skeletonCount?: number;
69
+ skeletonComponent?: React.ReactElement;
70
+
71
+ // Empty State
72
+ noDataComponent?: React.ReactNode;
73
+ noDataText?: string;
74
+
75
+ // Interaction
76
+ onPressItem?: (item: IPurchaseHistoryItem) => void;
77
+
78
+ onEndReached?: () => void;
79
+ onEndReachedThreshold?: number;
80
+ }
81
+
82
+ export const PurchaseHistory: React.FC<PurchaseHistoryProps> = ({
83
+ data = [],
84
+ isLoading = false,
85
+ title = 'Purchase History',
86
+ headerComponent,
87
+ onBackPress = () => {},
88
+ onSearchPress = () => {},
89
+ showSearchIcon = true,
90
+ itemDimension = 90,
91
+ spacing = 10,
92
+ listStyle,
93
+ contentContainerStyle,
94
+ theme,
95
+ renderItem,
96
+ skeletonCount = 9,
97
+ skeletonComponent,
98
+ noDataComponent,
99
+ noDataText = 'No Purchase History Found',
100
+ onPressItem,
101
+
102
+ onEndReached,
103
+ onEndReachedThreshold,
104
+ }) => {
105
+ const { theme: appliedTheme } = useInternalTheme(theme);
106
+
107
+ const listData = isLoading
108
+ ? Array.from({ length: skeletonCount }, (_, i) => ({
109
+ _id: `skeleton-${i}`,
110
+ }))
111
+ : data;
112
+
113
+ const formatDate = (dateString: string): string => {
114
+ const m = moment(dateString);
115
+ if (!m.isValid()) return 'Invalid Date';
116
+
117
+ const now = moment();
118
+ const daysDiff = m.diff(now, 'days');
119
+
120
+ // Show relative time for recent dates
121
+ if (daysDiff === 0) {
122
+ return 'Today';
123
+ } else if (daysDiff === -1) {
124
+ return 'Yesterday';
125
+ } else if (daysDiff > -7 && daysDiff < 0) {
126
+ return `${Math.abs(daysDiff)} days ago`;
127
+ }
128
+
129
+ // Show full date for older dates
130
+ if (m.year() === now.year()) {
131
+ return m.format('D MMM');
132
+ }
133
+ return m.format('D MMM YYYY');
134
+ };
135
+
136
+ const getTimeLeft = (dateString: string): string => {
137
+ const expiry = moment(dateString);
138
+ if (!expiry.isValid()) return '';
139
+
140
+ const now = moment();
141
+ if (expiry.isBefore(now)) return 'Expired';
142
+
143
+ const dur = moment.duration(expiry.diff(now));
144
+ const days = Math.floor(dur.asDays());
145
+ const hours = dur.hours();
146
+ const minutes = dur.minutes();
147
+ const seconds = dur.seconds();
148
+
149
+ if (days > 0) {
150
+ if (hours === 0) {
151
+ return `${days}d left`;
152
+ }
153
+ return `${days}d ${hours}h left`;
154
+ }
155
+
156
+ if (hours > 0) {
157
+ if (minutes === 0) {
158
+ return `${hours}h left`;
159
+ }
160
+ return `${hours}h ${minutes}m left`;
161
+ }
162
+
163
+ if (minutes > 0) {
164
+ return `${minutes}m left`;
165
+ }
166
+
167
+ return `${seconds}s left`;
168
+ };
169
+
170
+ const getChipColors = (
171
+ expired: boolean,
172
+ _tvodType?: IPurchaseHistoryItem['tvod_type']
173
+ ) => {
174
+ if (expired) {
175
+ return {
176
+ bg: appliedTheme.colors.background,
177
+ border: appliedTheme.colors.error,
178
+ text: appliedTheme.colors.error,
179
+ icon: appliedTheme.colors.error,
180
+ };
181
+ }
182
+
183
+ // Same colors for both RENT and BUY
184
+ return {
185
+ bg: appliedTheme.colors.background,
186
+ border: appliedTheme.colors.primary,
187
+ text: appliedTheme.colors.textPrimary,
188
+ icon: appliedTheme.colors.textPrimary,
189
+ };
190
+ };
191
+
192
+ const isExpired = (item: IPurchaseHistoryItem): boolean => {
193
+ if (item.status === 'expired') return true;
194
+ const expiry = moment(item.valid_upto);
195
+ if (!expiry.isValid()) return false;
196
+ return expiry.isBefore(moment());
197
+ };
198
+
199
+ const renderGridItem: ListRenderItem<any> = ({
200
+ item,
201
+ index,
202
+ }: {
203
+ item: IPurchaseHistoryItem;
204
+ index: number;
205
+ }) => {
206
+ if (isLoading && skeletonComponent) return skeletonComponent;
207
+ if (!isLoading && renderItem) return renderItem(item, index);
208
+
209
+ const expired = !isLoading && item ? isExpired(item) : false;
210
+ const statusColor = expired
211
+ ? appliedTheme.colors.error
212
+ : appliedTheme.colors.primary;
213
+
214
+ const statusTextColor = appliedTheme.colors.buttonText;
215
+
216
+ return (
217
+ <TouchableOpacity
218
+ onPress={() => onPressItem?.(item)}
219
+ activeOpacity={0.8}
220
+ style={styles.itemContainer}
221
+ >
222
+ <View style={styles.posterWrapper}>
223
+ <CardPoster
224
+ theme={appliedTheme}
225
+ isLoading={isLoading}
226
+ posterUri={item?.content_id?.poster}
227
+ />
228
+
229
+ {/* Gradient Overlay */}
230
+ {!isLoading && item && (
231
+ <LinearGradient
232
+ colors={[
233
+ 'rgba(0, 0, 0, 0.95)',
234
+ 'rgba(0, 0, 0, 0.5)',
235
+ 'rgba(0, 0, 0, 0.1)',
236
+ 'transparent',
237
+ ]}
238
+ locations={[0, 0.3, 0.6, 1]}
239
+ style={styles.gradientOverlay}
240
+ start={{ x: 0, y: 1 }}
241
+ end={{ x: 0, y: 0 }}
242
+ />
243
+ )}
244
+
245
+ {!isLoading && item && (
246
+ <>
247
+ {/* Status Badge */}
248
+ <View
249
+ style={[
250
+ styles.statusBadge,
251
+ {
252
+ backgroundColor: statusColor,
253
+ borderColor: statusColor,
254
+ },
255
+ ]}
256
+ >
257
+ {expired ? (
258
+ <XCircle size={scale(10)} color={statusTextColor} />
259
+ ) : (
260
+ <CheckCircle2 size={scale(10)} color={statusTextColor} />
261
+ )}
262
+ <Text style={[styles.statusText, { color: statusTextColor }]}>
263
+ {expired ? 'Expired' : 'Active'}
264
+ </Text>
265
+ </View>
266
+
267
+ {/* Expiry Date Overlay */}
268
+ <View style={styles.dateOverlay}>
269
+ {(() => {
270
+ const chip = getChipColors(expired, item.tvod_type);
271
+ return (
272
+ <View
273
+ style={[
274
+ styles.dateContainer,
275
+ { backgroundColor: chip.bg, borderColor: chip.border },
276
+ ]}
277
+ >
278
+ <View
279
+ style={[
280
+ styles.statusDot,
281
+ { backgroundColor: chip.border },
282
+ ]}
283
+ />
284
+ <Calendar size={scale(8)} color={chip.icon} />
285
+ <Text
286
+ style={[styles.dateText, { color: chip.text }]}
287
+ numberOfLines={1}
288
+ >
289
+ {expired
290
+ ? `Exp: ${formatDate(item.valid_upto)}`
291
+ : item.tvod_type === 'RENT'
292
+ ? getTimeLeft(item.valid_upto)
293
+ : 'Purchased'}
294
+ </Text>
295
+ </View>
296
+ );
297
+ })()}
298
+ </View>
299
+ </>
300
+ )}
301
+ </View>
302
+ </TouchableOpacity>
303
+ );
304
+ };
305
+
306
+ return (
307
+ <View style={styles.container}>
308
+ {headerComponent ? (
309
+ headerComponent
310
+ ) : (
311
+ <AppHeader
312
+ onBackPress={onBackPress}
313
+ title={title}
314
+ titleAlign="left"
315
+ theme={theme}
316
+ titleStyle={{
317
+ color: appliedTheme.colors.onBackground,
318
+ }}
319
+ onRightPress={onSearchPress}
320
+ rightIcon={
321
+ showSearchIcon ? (
322
+ <Search
323
+ size={scale(23)}
324
+ color={appliedTheme.colors.onBackground}
325
+ />
326
+ ) : undefined
327
+ }
328
+ />
329
+ )}
330
+
331
+ {isLoading || data.length > 0 ? (
332
+ <FlatGrid
333
+ itemDimension={itemDimension}
334
+ spacing={spacing}
335
+ data={listData}
336
+ keyExtractor={(item, index) => item._id || `item-${index}`}
337
+ style={listStyle}
338
+ contentContainerStyle={[
339
+ contentContainerStyle,
340
+ { paddingBottom: scale(50) },
341
+ ]}
342
+ renderItem={renderGridItem}
343
+ onEndReached={onEndReached}
344
+ onEndReachedThreshold={onEndReachedThreshold ?? 0.5}
345
+ />
346
+ ) : noDataComponent ? (
347
+ <>{noDataComponent}</>
348
+ ) : (
349
+ <View style={styles.noData}>
350
+ <Text style={styles.noDataText}>{noDataText}</Text>
351
+ </View>
352
+ )}
353
+ </View>
354
+ );
355
+ };
356
+
357
+ const styles = StyleSheet.create({
358
+ container: {
359
+ flex: 1,
360
+ },
361
+ itemContainer: {
362
+ width: '100%',
363
+ },
364
+ posterWrapper: {
365
+ width: '100%',
366
+ position: 'relative',
367
+ },
368
+ gradientOverlay: {
369
+ position: 'absolute',
370
+ top: 0,
371
+ left: 0,
372
+ right: 0,
373
+ bottom: 0,
374
+ zIndex: 1,
375
+ borderRadius: scale(6),
376
+ },
377
+ statusBadge: {
378
+ position: 'absolute',
379
+ top: scale(4),
380
+ right: scale(4),
381
+ flexDirection: 'row',
382
+ alignItems: 'center',
383
+ paddingHorizontal: scale(3),
384
+ paddingVertical: scale(1),
385
+ borderRadius: scale(10),
386
+ borderWidth: scale(1),
387
+ gap: scale(3),
388
+ zIndex: 100,
389
+ elevation: 8,
390
+ shadowColor: '#000',
391
+ shadowOffset: { width: 0, height: 2 },
392
+ shadowOpacity: 0.4,
393
+ shadowRadius: 4,
394
+ },
395
+ statusText: {
396
+ fontSize: RFValue(8),
397
+ fontWeight: '700',
398
+ color: '#FFFFFF',
399
+ },
400
+ dateOverlay: {
401
+ position: 'absolute',
402
+ bottom: 0,
403
+ left: 0,
404
+ right: 0,
405
+ padding: scale(4),
406
+ zIndex: 100,
407
+ },
408
+ dateContainer: {
409
+ flexDirection: 'row',
410
+ alignItems: 'center',
411
+ paddingHorizontal: scale(5),
412
+ paddingVertical: scale(4),
413
+ borderRadius: scale(4),
414
+ gap: scale(3),
415
+ borderWidth: scale(0.8),
416
+ },
417
+ statusDot: { width: scale(6), height: scale(6), borderRadius: scale(3) },
418
+ dateText: {
419
+ fontSize: RFValue(7),
420
+ fontWeight: '600',
421
+ flex: 1,
422
+ lineHeight: RFValue(9),
423
+ },
424
+ noData: {
425
+ flex: 1,
426
+ alignItems: 'center',
427
+ justifyContent: 'center',
428
+ },
429
+ noDataText: {
430
+ fontSize: RFValue(12),
431
+ opacity: 0.5,
432
+ },
433
+ });
434
+
435
+ export namespace PurchaseHistory {
436
+ export type Props = PurchaseHistoryProps;
437
+ export type Data = Props['data'];
438
+ export type Item = Props['data'][number];
439
+ }
@@ -7,5 +7,12 @@ import { WatchHistory } from './WatchHistory/WatchHistory';
7
7
  import { WatchLater } from './WatchLater/WatchLater';
8
8
  import { DeviceSessions } from './DeviceSessions/DeviceSessions';
9
9
  import { ProfileUpdate } from './ProfileUpdate/ProfileUpdate';
10
+ import { PurchaseHistory } from './PurchaseHistory/PurchaseHistory';
10
11
 
11
- export { WatchHistory, WatchLater, DeviceSessions, ProfileUpdate };
12
+ export {
13
+ WatchHistory,
14
+ WatchLater,
15
+ DeviceSessions,
16
+ ProfileUpdate,
17
+ PurchaseHistory,
18
+ };
@@ -25,3 +25,4 @@ export * from './Search';
25
25
  export * from './Subscription';
26
26
  export * from './Alert';
27
27
  export * from './Reels';
28
+ export * from './BlurView';
@@ -0,0 +1,35 @@
1
+ /**
2
+ * @author Naresh Dhamu
3
+ * @lastModified Thu 06 Nov 2025 at 11:52 AM
4
+ */
5
+
6
+ import { useEffect, useState } from 'react';
7
+ import NavigationMode from 'react-native-navigation-mode';
8
+
9
+ /**
10
+ * Hook to detect Android navigation mode
11
+ * @returns {Object} Navigation mode info
12
+ * @returns {boolean} isThreeButtonNav - true if using three-button navigation
13
+ * @returns {boolean} isGestureNav - true if using gesture navigation
14
+ */
15
+ export const useNavigationMode = () => {
16
+ const [isThreeButtonNav, setIsThreeButtonNav] = useState(false);
17
+
18
+ useEffect(() => {
19
+ (async () => {
20
+ try {
21
+ const navMode = (await NavigationMode.getNavigationMode()) as any;
22
+ const isThreeButton =
23
+ navMode?.navigationMode === 'THREE_BUTTON' ||
24
+ navMode?.mode === 'THREE_BUTTON';
25
+ setIsThreeButtonNav(isThreeButton);
26
+ } catch (err) {
27
+ console.log('Navigation mode detect error:', err);
28
+ }
29
+ })();
30
+ }, []);
31
+
32
+ return {
33
+ isGestureNav: !isThreeButtonNav,
34
+ };
35
+ };
@@ -11,6 +11,7 @@ import type { IGetSectionData, ISectionItem } from '../../types/sections';
11
11
  import type { MoreFetchData } from '../../types/hook/usePaginatedSetion';
12
12
  import type { IHistoryItem } from '../../components/User/WatchHistory/WatchHistory';
13
13
  import type React from 'react';
14
+ import type { MiniInfo } from '../../components/ContentView/components/MiniInfo';
14
15
 
15
16
  // 🔷 Common Style Aliases
16
17
  export type ViewStyleProp = StyleProp<ViewStyle>;
@@ -145,6 +146,10 @@ export type ComponentProps = {
145
146
  };
146
147
  theme?: ThemeOverride;
147
148
  isLoading?: boolean;
149
+ pricingAndExpiryInfo?: Omit<
150
+ React.ComponentProps<typeof MiniInfo>,
151
+ 'content' | 'theme'
152
+ >;
148
153
  seasonsIsLoading?: boolean;
149
154
  recommendedContent?: ISectionItem | null;
150
155
  events?: ContentViewEvents;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @author Naresh Dhamu
3
+ * @lastModified Mon 16 Jun 2025 at 03:05 PM
4
+ */
5
+
6
+ import { Platform } from 'react-native';
7
+ import { verticalScale } from 'react-native-size-matters';
8
+
9
+ /**
10
+ * Get responsive bottom spacing that accounts for platform differences
11
+ * Automatically adds extra spacing for Android navigation bar
12
+ * @param baseSpacing - Base spacing value (default: 35)
13
+ * @returns Platform-specific responsive bottom spacing
14
+ * @example
15
+ * // Usage in any component
16
+ * bottom: getResponsiveBottomSpacing(35) // iOS: 35, Android: 45
17
+ */
18
+ export const getResponsiveBottomSpacing = (
19
+ baseSpacing: number = 35
20
+ ): number => {
21
+ return Platform.OS === 'ios'
22
+ ? verticalScale(baseSpacing)
23
+ : verticalScale(baseSpacing + 10);
24
+ };
25
+
26
+ // Legacy export for backward compatibility
27
+ export const getAuthBottomSpacing = getResponsiveBottomSpacing;