@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.
- package/README.md +1 -1
- package/lib/module/components/Account/Account.js +1 -1
- package/lib/module/components/Account/Account.js.map +1 -1
- package/lib/module/components/Auth/AuthProvider/AuthProvider.js +48 -19
- package/lib/module/components/Auth/AuthProvider/AuthProvider.js.map +1 -1
- package/lib/module/components/Auth/Login/LoginWithEmail.js +4 -2
- package/lib/module/components/Auth/Login/LoginWithEmail.js.map +1 -1
- package/lib/module/components/Auth/OTP/OTP.js +15 -1
- package/lib/module/components/Auth/OTP/OTP.js.map +1 -1
- package/lib/module/components/Auth/SignUp/SignUp.js +4 -2
- package/lib/module/components/Auth/SignUp/SignUp.js.map +1 -1
- package/lib/module/components/BlurView/BlurView.js +171 -0
- package/lib/module/components/BlurView/BlurView.js.map +1 -0
- package/lib/module/components/BlurView/index.js +9 -0
- package/lib/module/components/BlurView/index.js.map +1 -0
- package/lib/module/components/Content/Card/Styles/Four.js +1 -1
- package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
- package/lib/module/components/Content/Content.js +4 -2
- package/lib/module/components/Content/Content.js.map +1 -1
- package/lib/module/components/ContentView/ContentView.js +4 -2
- package/lib/module/components/ContentView/ContentView.js.map +1 -1
- package/lib/module/components/ContentView/components/MiniInfo.js +64 -19
- package/lib/module/components/ContentView/components/MiniInfo.js.map +1 -1
- package/lib/module/components/Settings/AppSettings.js +1 -1
- package/lib/module/components/Settings/AppSettings.js.map +1 -1
- package/lib/module/components/Subscription/SubOne.js +340 -13
- package/lib/module/components/Subscription/SubOne.js.map +1 -1
- package/lib/module/components/TabBar/One.js +71 -108
- package/lib/module/components/TabBar/One.js.map +1 -1
- package/lib/module/components/TabBar/Three.js +63 -78
- package/lib/module/components/TabBar/Three.js.map +1 -1
- package/lib/module/components/TabBar/Two.js +110 -106
- package/lib/module/components/TabBar/Two.js.map +1 -1
- package/lib/module/components/User/PurchaseHistory/PurchaseHistory.js +324 -0
- package/lib/module/components/User/PurchaseHistory/PurchaseHistory.js.map +1 -0
- package/lib/module/components/User/index.js +2 -1
- package/lib/module/components/User/index.js.map +1 -1
- package/lib/module/components/index.js +1 -0
- package/lib/module/components/index.js.map +1 -1
- package/lib/module/hooks/useNavigationMode.js +34 -0
- package/lib/module/hooks/useNavigationMode.js.map +1 -0
- package/lib/module/utils/Spacing.js +26 -0
- package/lib/module/utils/Spacing.js.map +1 -0
- package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts +1 -0
- package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts.map +1 -1
- package/lib/typescript/src/components/Auth/Login/LoginWithEmail.d.ts.map +1 -1
- package/lib/typescript/src/components/Auth/OTP/OTP.d.ts +2 -0
- package/lib/typescript/src/components/Auth/OTP/OTP.d.ts.map +1 -1
- package/lib/typescript/src/components/Auth/SignUp/SignUp.d.ts.map +1 -1
- package/lib/typescript/src/components/Auth/index.d.ts +2 -0
- package/lib/typescript/src/components/Auth/index.d.ts.map +1 -1
- package/lib/typescript/src/components/BlurView/BlurView.d.ts +48 -0
- package/lib/typescript/src/components/BlurView/BlurView.d.ts.map +1 -0
- package/lib/typescript/src/components/BlurView/index.d.ts +7 -0
- package/lib/typescript/src/components/BlurView/index.d.ts.map +1 -0
- package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
- package/lib/typescript/src/components/ContentView/ContentView.d.ts +1 -1
- package/lib/typescript/src/components/ContentView/ContentView.d.ts.map +1 -1
- package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts +17 -1
- package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts.map +1 -1
- package/lib/typescript/src/components/Subscription/SubOne.d.ts +6 -0
- package/lib/typescript/src/components/Subscription/SubOne.d.ts.map +1 -1
- package/lib/typescript/src/components/Subscription/index.d.ts.map +1 -1
- package/lib/typescript/src/components/TabBar/One.d.ts +2 -2
- package/lib/typescript/src/components/TabBar/One.d.ts.map +1 -1
- package/lib/typescript/src/components/TabBar/Three.d.ts +3 -2
- package/lib/typescript/src/components/TabBar/Three.d.ts.map +1 -1
- package/lib/typescript/src/components/TabBar/Two.d.ts +13 -4
- package/lib/typescript/src/components/TabBar/Two.d.ts.map +1 -1
- package/lib/typescript/src/components/TabBar/index.d.ts +1 -1
- package/lib/typescript/src/components/User/PurchaseHistory/PurchaseHistory.d.ts +50 -0
- package/lib/typescript/src/components/User/PurchaseHistory/PurchaseHistory.d.ts.map +1 -0
- package/lib/typescript/src/components/User/index.d.ts +2 -1
- package/lib/typescript/src/components/User/index.d.ts.map +1 -1
- package/lib/typescript/src/components/index.d.ts +1 -0
- package/lib/typescript/src/components/index.d.ts.map +1 -1
- package/lib/typescript/src/hooks/useNavigationMode.d.ts +14 -0
- package/lib/typescript/src/hooks/useNavigationMode.d.ts.map +1 -0
- package/lib/typescript/src/types/content/content-view.types.d.ts +2 -0
- package/lib/typescript/src/types/content/content-view.types.d.ts.map +1 -1
- package/lib/typescript/src/utils/Spacing.d.ts +16 -0
- package/lib/typescript/src/utils/Spacing.d.ts.map +1 -0
- package/package.json +9 -5
- package/src/components/Account/Account.tsx +1 -1
- package/src/components/Auth/AuthProvider/AuthProvider.tsx +82 -37
- package/src/components/Auth/Login/LoginWithEmail.tsx +9 -2
- package/src/components/Auth/OTP/OTP.tsx +37 -1
- package/src/components/Auth/SignUp/SignUp.tsx +9 -2
- package/src/components/BlurView/BlurView.tsx +199 -0
- package/src/components/BlurView/index.ts +7 -0
- package/src/components/Content/Card/Styles/Four.tsx +3 -1
- package/src/components/Content/Content.tsx +5 -4
- package/src/components/ContentView/ContentView.tsx +8 -1
- package/src/components/ContentView/components/MiniInfo.tsx +99 -22
- package/src/components/Settings/AppSettings.tsx +1 -1
- package/src/components/Subscription/SubOne.tsx +422 -11
- package/src/components/TabBar/One.tsx +79 -141
- package/src/components/TabBar/Three.tsx +84 -99
- package/src/components/TabBar/Two.tsx +139 -110
- package/src/components/User/PurchaseHistory/PurchaseHistory.tsx +439 -0
- package/src/components/User/index.ts +8 -1
- package/src/components/index.ts +1 -0
- package/src/hooks/useNavigationMode.ts +35 -0
- package/src/types/content/content-view.types.ts +5 -0
- 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 {
|
|
12
|
+
export {
|
|
13
|
+
WatchHistory,
|
|
14
|
+
WatchLater,
|
|
15
|
+
DeviceSessions,
|
|
16
|
+
ProfileUpdate,
|
|
17
|
+
PurchaseHistory,
|
|
18
|
+
};
|
package/src/components/index.ts
CHANGED
|
@@ -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;
|