@zezosoft/zezo-ott-react-native-ui-kit 1.0.3 → 1.0.4

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 (108) hide show
  1. package/README.md +1 -1
  2. package/lib/module/assets/animations/heart.json +788 -0
  3. package/lib/module/components/Auth/QrLogin/QrLogin.js +267 -0
  4. package/lib/module/components/Auth/QrLogin/QrLogin.js.map +1 -0
  5. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js +178 -0
  6. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js.map +1 -0
  7. package/lib/module/components/Auth/index.js +3 -1
  8. package/lib/module/components/Auth/index.js.map +1 -1
  9. package/lib/module/components/Headers/AppHeader.js +1 -1
  10. package/lib/module/components/Headers/AppHeader.js.map +1 -1
  11. package/lib/module/components/Headers/One.js +1 -1
  12. package/lib/module/components/Headers/One.js.map +1 -1
  13. package/lib/module/components/Headers/Two.js +1 -1
  14. package/lib/module/components/Headers/Two.js.map +1 -1
  15. package/lib/module/components/Reels/ReelsSeries/Model/Episodes.js +110 -0
  16. package/lib/module/components/Reels/ReelsSeries/Model/Episodes.js.map +1 -0
  17. package/lib/module/components/Reels/ReelsSeries/Model/Synopsis.js +216 -0
  18. package/lib/module/components/Reels/ReelsSeries/Model/Synopsis.js.map +1 -0
  19. package/lib/module/components/Reels/ReelsSeries/ReelSeriesDetailsModal.js +182 -0
  20. package/lib/module/components/Reels/ReelsSeries/ReelSeriesDetailsModal.js.map +1 -0
  21. package/lib/module/components/Reels/ReelsSeries/ReelSeriesOverlay.js +203 -0
  22. package/lib/module/components/Reels/ReelsSeries/ReelSeriesOverlay.js.map +1 -0
  23. package/lib/module/components/Reels/ReelsSeries/ReelsSeries.js +121 -0
  24. package/lib/module/components/Reels/ReelsSeries/ReelsSeries.js.map +1 -0
  25. package/lib/module/components/Reels/ReelsSeries/ReelsSeriesItem.js +290 -0
  26. package/lib/module/components/Reels/ReelsSeries/ReelsSeriesItem.js.map +1 -0
  27. package/lib/module/components/Reels/ReelsSeries/types.js +2 -0
  28. package/lib/module/components/Reels/ReelsSeries/types.js.map +1 -0
  29. package/lib/module/components/Reels/index.js +11 -0
  30. package/lib/module/components/Reels/index.js.map +1 -0
  31. package/lib/module/components/User/DeviceSessions/DeviceSessions.js +8 -0
  32. package/lib/module/components/User/DeviceSessions/DeviceSessions.js.map +1 -1
  33. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js +258 -0
  34. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js.map +1 -0
  35. package/lib/module/components/User/components/UserSection.js +8 -13
  36. package/lib/module/components/User/components/UserSection.js.map +1 -1
  37. package/lib/module/components/User/index.js +2 -1
  38. package/lib/module/components/User/index.js.map +1 -1
  39. package/lib/module/components/index.js +1 -0
  40. package/lib/module/components/index.js.map +1 -1
  41. package/lib/module/theme/ThemeProvider.js +13 -10
  42. package/lib/module/theme/ThemeProvider.js.map +1 -1
  43. package/lib/module/theme/themes.js +2 -0
  44. package/lib/module/theme/themes.js.map +1 -1
  45. package/lib/module/utils/Formater.js +17 -0
  46. package/lib/module/utils/Formater.js.map +1 -0
  47. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts +32 -0
  48. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts.map +1 -0
  49. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts +15 -0
  50. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts.map +1 -0
  51. package/lib/typescript/src/components/Auth/index.d.ts +1 -0
  52. package/lib/typescript/src/components/Auth/index.d.ts.map +1 -1
  53. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Episodes.d.ts +12 -0
  54. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Episodes.d.ts.map +1 -0
  55. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Synopsis.d.ts +9 -0
  56. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Synopsis.d.ts.map +1 -0
  57. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.d.ts +13 -0
  58. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.d.ts.map +1 -0
  59. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesOverlay.d.ts +18 -0
  60. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesOverlay.d.ts.map +1 -0
  61. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeries.d.ts +15 -0
  62. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeries.d.ts.map +1 -0
  63. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeriesItem.d.ts +18 -0
  64. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeriesItem.d.ts.map +1 -0
  65. package/lib/typescript/src/components/Reels/ReelsSeries/types.d.ts +24 -0
  66. package/lib/typescript/src/components/Reels/ReelsSeries/types.d.ts.map +1 -0
  67. package/lib/typescript/src/components/Reels/index.d.ts +8 -0
  68. package/lib/typescript/src/components/Reels/index.d.ts.map +1 -0
  69. package/lib/typescript/src/components/User/DeviceSessions/DeviceSessions.d.ts +1 -0
  70. package/lib/typescript/src/components/User/DeviceSessions/DeviceSessions.d.ts.map +1 -1
  71. package/lib/typescript/src/components/User/ProfileUpdate/ProfileUpdate.d.ts +27 -0
  72. package/lib/typescript/src/components/User/ProfileUpdate/ProfileUpdate.d.ts.map +1 -0
  73. package/lib/typescript/src/components/User/components/UserSection.d.ts.map +1 -1
  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/theme/ThemeProvider.d.ts.map +1 -1
  79. package/lib/typescript/src/theme/themes.d.ts +1 -0
  80. package/lib/typescript/src/theme/themes.d.ts.map +1 -1
  81. package/lib/typescript/src/utils/Formater.d.ts +2 -0
  82. package/lib/typescript/src/utils/Formater.d.ts.map +1 -0
  83. package/package.json +13 -5
  84. package/src/assets/animations/heart.json +788 -0
  85. package/src/components/Auth/QrLogin/QrLogin.tsx +306 -0
  86. package/src/components/Auth/QrLogin/components/QrViewArea.tsx +213 -0
  87. package/src/components/Auth/index.ts +2 -0
  88. package/src/components/Headers/AppHeader.tsx +1 -1
  89. package/src/components/Headers/One.tsx +1 -1
  90. package/src/components/Headers/Two.tsx +1 -1
  91. package/src/components/Reels/ReelsSeries/Model/Episodes.tsx +133 -0
  92. package/src/components/Reels/ReelsSeries/Model/Synopsis.tsx +249 -0
  93. package/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.tsx +209 -0
  94. package/src/components/Reels/ReelsSeries/ReelSeriesOverlay.tsx +185 -0
  95. package/src/components/Reels/ReelsSeries/ReelsSeries.tsx +163 -0
  96. package/src/components/Reels/ReelsSeries/ReelsSeriesItem.tsx +333 -0
  97. package/src/components/Reels/ReelsSeries/types.ts +27 -0
  98. package/src/components/Reels/index.ts +8 -0
  99. package/src/components/User/DeviceSessions/DeviceSessions.tsx +11 -0
  100. package/src/components/User/ProfileUpdate/ProfileUpdate.tsx +265 -0
  101. package/src/components/User/components/UserSection.tsx +10 -13
  102. package/src/components/User/index.ts +3 -1
  103. package/src/components/index.ts +1 -0
  104. package/src/theme/ThemeProvider.tsx +12 -9
  105. package/src/theme/themes.ts +3 -0
  106. package/src/utils/Formater.ts +14 -0
  107. /package/lib/module/assets/{img → svg}/h.svg +0 -0
  108. /package/src/assets/{img → svg}/h.svg +0 -0
@@ -0,0 +1,249 @@
1
+ import React, { useCallback } from 'react';
2
+ import {
3
+ Text,
4
+ View,
5
+ Image,
6
+ StyleSheet,
7
+ TouchableOpacity,
8
+ Dimensions,
9
+ FlatList,
10
+ } from 'react-native';
11
+ import { RFValue } from 'react-native-responsive-fontsize';
12
+ import { moderateScale, scale, verticalScale } from 'react-native-size-matters';
13
+ import type { ISeriesEpisode, ISeriesItem } from '../types';
14
+ import Svg, { Path, Defs, LinearGradient, Stop } from 'react-native-svg';
15
+
16
+ const { width: SCREEN_WIDTH } = Dimensions.get('window');
17
+ const GAP = moderateScale(10);
18
+
19
+ interface SynopsisProps {
20
+ reel: ISeriesEpisode;
21
+ data: ISeriesItem;
22
+ }
23
+
24
+ interface ILikeMoreData {
25
+ id: number;
26
+ name: string;
27
+ thumbnail: string;
28
+ }
29
+
30
+ const likeMoreData: Array<ILikeMoreData> = [
31
+ {
32
+ id: 1,
33
+ name: 'Housefull 5',
34
+ thumbnail:
35
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTZFKczA4mK0DoFSiKN75aAtWdhm_AZvCWGkwPl2StUpOQYq6_b',
36
+ },
37
+ {
38
+ id: 2,
39
+ name: 'Sample Episode',
40
+ thumbnail:
41
+ 'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcTfRd3dwJUToDAbEB4afBWcic5_HCwbKbn-B7-ZgF7niTa-MTIt',
42
+ },
43
+ {
44
+ id: 3,
45
+ name: 'Tees Maar Khan',
46
+ thumbnail:
47
+ 'https://encrypted-tbn3.gstatic.com/images?q=tbn:ANd9GcSwz8vklTTg8YdCqRHg9aauHq9BgpVgxLUvldi-Doz_Eh7ZIiVl',
48
+ },
49
+ {
50
+ id: 4,
51
+ name: 'Aap Jaisa Koi',
52
+ thumbnail:
53
+ 'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcQujccf3ymM7lkv83Y6TkS5BkcLYJLTu2d3rJQYxh6cGqwx8AuR',
54
+ },
55
+ {
56
+ id: 5,
57
+ name: 'Kaalidhar Laapata',
58
+ thumbnail:
59
+ 'https://upload.wikimedia.org/wikipedia/en/b/bd/Kaalidhar_Laapata.jpg',
60
+ },
61
+ {
62
+ id: 6,
63
+ name: 'Aankhon Ki Gustaakhiyan',
64
+ thumbnail:
65
+ 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSLqG-A_lUucNT4TOcY1u42ujHyPbwuJvRLbO4zjNS8iuzNQ_6X',
66
+ },
67
+ ];
68
+
69
+ const Synopsis: React.FC<SynopsisProps> = ({ data }) => {
70
+ // responsive columns
71
+ const numColumns = SCREEN_WIDTH >= 420 ? 4 : 3;
72
+ const keyExtractor = useCallback(
73
+ (item: ILikeMoreData) => item.id.toString(),
74
+ []
75
+ );
76
+
77
+ const renderItem = useCallback(
78
+ ({ item }: { item: ILikeMoreData; index: number }) => (
79
+ <TouchableOpacity
80
+ style={[styles.card]}
81
+ activeOpacity={0.8}
82
+ onPress={() => {
83
+ // Handle item press if needed
84
+ console.log('Pressed item:', item.name);
85
+ }}
86
+ >
87
+ <Image
88
+ source={{
89
+ uri:
90
+ item.thumbnail ||
91
+ 'https://via.placeholder.com/300x400?text=Episode',
92
+ }}
93
+ style={styles.thumbnail}
94
+ resizeMode="cover"
95
+ />
96
+ <Text
97
+ style={[styles.title, { color: '#fff', width: scale(90) }]}
98
+ numberOfLines={2}
99
+ >
100
+ {item.name || 'Untitled'}
101
+ </Text>
102
+ </TouchableOpacity>
103
+ ),
104
+ []
105
+ );
106
+
107
+ return (
108
+ <View style={styles.container}>
109
+ <Text
110
+ style={{
111
+ color: 'rgba(255,255,255,1)',
112
+ fontSize: RFValue(10),
113
+ lineHeight: RFValue(14),
114
+ marginBottom: verticalScale(12),
115
+ }}
116
+ >
117
+ {data.description ||
118
+ 'No synopsis available for this reel. Please check back later.'}
119
+ </Text>
120
+
121
+ {/* Header */}
122
+ <View style={styles.header}>
123
+ <Svg width={22} height={2} viewBox="0 0 22 2" fill="none">
124
+ <Path d="M21.692 1.196H.594" stroke="url(#a)" strokeWidth={1.005} />
125
+ <Defs>
126
+ <LinearGradient
127
+ id="a"
128
+ x1={0.594}
129
+ y1={1.696}
130
+ x2={21.692}
131
+ y2={1.696}
132
+ gradientUnits="userSpaceOnUse"
133
+ >
134
+ <Stop stopOpacity={0} />
135
+ <Stop offset={1} stopColor="#fff" />
136
+ </LinearGradient>
137
+ </Defs>
138
+ </Svg>
139
+ <Text
140
+ style={{
141
+ color: '#fff',
142
+ fontSize: 12,
143
+ textAlign: 'center',
144
+ marginHorizontal: scale(8),
145
+ }}
146
+ >
147
+ More Like This
148
+ </Text>
149
+ <Svg width={22} height={2} viewBox="0 0 22 2" fill="none">
150
+ <Path
151
+ d="M.312 1.196H21.41"
152
+ stroke="url(#paint0_linear_797_3114)"
153
+ strokeWidth={1.00467}
154
+ />
155
+ <Defs>
156
+ <LinearGradient
157
+ id="paint0_linear_797_3114"
158
+ x1={21.4102}
159
+ y1={1.69629}
160
+ x2={0.312025}
161
+ y2={1.69629}
162
+ gradientUnits="userSpaceOnUse"
163
+ >
164
+ <Stop stopOpacity={0} />
165
+ <Stop offset={1} stopColor="#fff" />
166
+ </LinearGradient>
167
+ </Defs>
168
+ </Svg>
169
+ </View>
170
+
171
+ {/* Episodes Grid */}
172
+ {likeMoreData.length === 0 ? (
173
+ <Text style={styles.noEpisodesText}>No recommendations available.</Text>
174
+ ) : (
175
+ <FlatList
176
+ data={likeMoreData}
177
+ keyExtractor={keyExtractor}
178
+ renderItem={renderItem}
179
+ numColumns={numColumns}
180
+ columnWrapperStyle={{
181
+ justifyContent: 'space-between',
182
+ marginBottom: GAP,
183
+ }}
184
+ showsVerticalScrollIndicator={false}
185
+ contentContainerStyle={{
186
+ paddingBottom: verticalScale(16),
187
+ }}
188
+ removeClippedSubviews={false} // Disable to prevent recycling issues
189
+ nestedScrollEnabled={true} // Allows scroll inside modal
190
+ getItemLayout={(_data, index) => ({
191
+ length: verticalScale(120) + verticalScale(6) + verticalScale(20), // thumbnail + margin + text
192
+ offset:
193
+ (verticalScale(120) + verticalScale(6) + verticalScale(20)) *
194
+ Math.floor(index / numColumns),
195
+ index,
196
+ })}
197
+ initialNumToRender={6}
198
+ maxToRenderPerBatch={6}
199
+ windowSize={5}
200
+ disableVirtualization={false}
201
+ />
202
+ )}
203
+ </View>
204
+ );
205
+ };
206
+
207
+ export default Synopsis;
208
+
209
+ const styles = StyleSheet.create({
210
+ container: { flex: 1 },
211
+ header: {
212
+ flexDirection: 'row',
213
+ alignItems: 'center',
214
+ justifyContent: 'center',
215
+ marginBottom: verticalScale(12),
216
+ },
217
+ headerLine: {
218
+ height: verticalScale(1.5),
219
+ width: moderateScale(50),
220
+ marginHorizontal: moderateScale(8),
221
+ borderRadius: 999,
222
+ },
223
+ headerLabel: {
224
+ fontSize: RFValue(12),
225
+ textAlign: 'center',
226
+ },
227
+ card: {
228
+ // alignItems: 'center',
229
+ },
230
+ thumbnail: {
231
+ width: '100%',
232
+ height: verticalScale(120),
233
+ borderRadius: moderateScale(8),
234
+ marginBottom: verticalScale(6),
235
+ backgroundColor: 'rgba(255,255,255,0.06)',
236
+ aspectRatio: 3 / 4,
237
+ },
238
+ title: {
239
+ fontSize: RFValue(10),
240
+ // textAlign: 'center',
241
+ },
242
+ noEpisodesText: {
243
+ color: 'rgba(180,180,180,1)',
244
+ fontSize: RFValue(13),
245
+ textAlign: 'center',
246
+ marginTop: verticalScale(8),
247
+ marginBottom: verticalScale(12),
248
+ },
249
+ });
@@ -0,0 +1,209 @@
1
+ import React, { useState } from 'react';
2
+ import {
3
+ View,
4
+ Text,
5
+ TouchableOpacity,
6
+ Image,
7
+ StyleSheet,
8
+ Dimensions,
9
+ } from 'react-native';
10
+ import Modal from 'react-native-modal';
11
+ import LinearGradient from 'react-native-linear-gradient';
12
+ import { X } from 'lucide-react-native';
13
+ import { moderateScale, verticalScale } from 'react-native-size-matters';
14
+ import { RFValue } from 'react-native-responsive-fontsize';
15
+ import Episodes from './Model/Episodes';
16
+ import Synopsis from './Model/Synopsis';
17
+ import type { ISeriesEpisode, ISeriesItem } from './types';
18
+ import { formatCount } from '../../../utils/Formater';
19
+
20
+ const { height } = Dimensions.get('window');
21
+
22
+ interface ReelSeriesDetailsModalProps {
23
+ visible: boolean;
24
+ onClose: () => void;
25
+ reel: ISeriesEpisode;
26
+ data: ISeriesItem;
27
+ activeEpisodeIndex: number;
28
+ onEpisodeSelect: (index: number) => void;
29
+ }
30
+
31
+ const ReelSeriesDetailsModal: React.FC<ReelSeriesDetailsModalProps> = ({
32
+ visible,
33
+ onClose,
34
+ reel,
35
+ data,
36
+ activeEpisodeIndex,
37
+ onEpisodeSelect,
38
+ }) => {
39
+ const [activeTab, setActiveTab] = useState<'synopsis' | 'episodes'>(
40
+ 'synopsis'
41
+ );
42
+ const [routes] = useState<
43
+ {
44
+ key: string;
45
+ title: string;
46
+ }[]
47
+ >([
48
+ { key: 'synopsis', title: 'Synopsis' },
49
+ { key: 'episodes', title: 'Episodes' },
50
+ ]);
51
+
52
+ return (
53
+ <Modal
54
+ isVisible={visible}
55
+ onBackdropPress={onClose}
56
+ swipeDirection="down"
57
+ onSwipeComplete={onClose}
58
+ backdropOpacity={0.5}
59
+ style={{ margin: 0, justifyContent: 'flex-end' }}
60
+ propagateSwipe
61
+ >
62
+ <LinearGradient
63
+ colors={['rgba(103,85,35,1)', 'rgba(21,21,21,1)']}
64
+ style={styles.bottomSheetContainer}
65
+ >
66
+ {/* Drag Handle */}
67
+ <View style={styles.dragHandle} />
68
+ {/* Close Button */}
69
+ <TouchableOpacity onPress={onClose} style={styles.closeButtonWrapper}>
70
+ <X size={moderateScale(16)} color={'#fff'} />
71
+ </TouchableOpacity>
72
+ {/* Creator + Title */}
73
+ <View style={styles.headerRow}>
74
+ <Image
75
+ source={{ uri: data.thumbnail }}
76
+ style={styles.reelPosterImage}
77
+ />
78
+ <View style={{ flex: 1 }}>
79
+ <Text style={styles.reelTitleText}>{data.title}</Text>
80
+ <Text style={styles.reelDescriptionText} numberOfLines={3}>
81
+ {data.description}
82
+ </Text>
83
+ <Text style={styles.reelViewsText}>
84
+ {formatCount(data.views || 0)} Views
85
+ </Text>
86
+ </View>
87
+ </View>
88
+ {/* Tab View */}
89
+ <View
90
+ style={{
91
+ flexDirection: 'row',
92
+ // justifyContent: 'space-around',
93
+ marginTop: verticalScale(10),
94
+ }}
95
+ >
96
+ {routes.map((item) => (
97
+ <TouchableOpacity
98
+ key={item.key}
99
+ style={{
100
+ borderBottomColor: 'white',
101
+ borderBottomWidth:
102
+ activeTab === routes.find((r) => r.key === item.key)?.key
103
+ ? 2
104
+ : 0,
105
+ paddingBottom: 6,
106
+ marginHorizontal: 12,
107
+ }}
108
+ onPress={() => {
109
+ const tab = routes.find((r) => r.key === item.key)?.key;
110
+ tab && setActiveTab(tab as 'synopsis' | 'episodes');
111
+ }}
112
+ >
113
+ <Text
114
+ style={{
115
+ color: 'white',
116
+ fontSize: RFValue(11),
117
+ fontWeight: '700',
118
+ opacity:
119
+ activeTab === routes.find((r) => r.key === item.key)?.key
120
+ ? 1
121
+ : 0.6,
122
+ }}
123
+ >
124
+ {item.title}
125
+ </Text>
126
+ </TouchableOpacity>
127
+ ))}
128
+ </View>
129
+ {/* Tab View Content */}
130
+ <View
131
+ style={{
132
+ flex: 1,
133
+ marginTop: verticalScale(8),
134
+ marginHorizontal: 12,
135
+ }}
136
+ >
137
+ {activeTab === 'synopsis' && <Synopsis reel={reel} data={data} />}
138
+ {activeTab === 'episodes' && (
139
+ <Episodes
140
+ reel={reel}
141
+ data={data}
142
+ currentReel={activeEpisodeIndex}
143
+ onEpisodeSelect={onEpisodeSelect}
144
+ />
145
+ )}
146
+ </View>
147
+ </LinearGradient>
148
+ </Modal>
149
+ );
150
+ };
151
+
152
+ export default ReelSeriesDetailsModal;
153
+
154
+ const styles = StyleSheet.create({
155
+ bottomSheetContainer: {
156
+ height: height * 0.9,
157
+ borderTopLeftRadius: moderateScale(20),
158
+ borderTopRightRadius: moderateScale(20),
159
+ overflow: 'hidden',
160
+ paddingTop: verticalScale(10),
161
+ },
162
+ dragHandle: {
163
+ width: moderateScale(50),
164
+ height: verticalScale(5),
165
+ borderRadius: moderateScale(3),
166
+ backgroundColor: 'rgba(255,255,255,0.5)',
167
+ alignSelf: 'center',
168
+ marginBottom: verticalScale(10),
169
+ },
170
+ closeButtonWrapper: {
171
+ position: 'absolute',
172
+ top: verticalScale(10),
173
+ right: moderateScale(14),
174
+ zIndex: 10,
175
+ borderRadius: moderateScale(18),
176
+ width: moderateScale(30),
177
+ height: moderateScale(30),
178
+ justifyContent: 'center',
179
+ alignItems: 'center',
180
+ backgroundColor: 'rgba(255,255,255,0.26)',
181
+ },
182
+ headerRow: {
183
+ flexDirection: 'row',
184
+ paddingHorizontal: moderateScale(16),
185
+ marginBottom: verticalScale(10),
186
+ },
187
+ reelPosterImage: {
188
+ width: moderateScale(80),
189
+ height: verticalScale(100),
190
+ borderRadius: moderateScale(8),
191
+ marginRight: moderateScale(12),
192
+ },
193
+ reelTitleText: {
194
+ fontSize: RFValue(14),
195
+ fontWeight: '600',
196
+ color: '#fff',
197
+ },
198
+ reelDescriptionText: {
199
+ fontSize: RFValue(10),
200
+ color: 'rgba(215,215,215,1)',
201
+ marginBottom: verticalScale(4),
202
+ marginTop: verticalScale(3.5),
203
+ },
204
+ reelViewsText: {
205
+ fontSize: RFValue(10),
206
+ color: 'rgba(215,215,215,1)',
207
+ marginTop: verticalScale(2),
208
+ },
209
+ });
@@ -0,0 +1,185 @@
1
+ import React from 'react';
2
+ import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
3
+ import { Heart, Forward, ChevronRight, ListVideo } from 'lucide-react-native';
4
+ import { moderateScale, verticalScale } from 'react-native-size-matters';
5
+ import { RFValue } from 'react-native-responsive-fontsize';
6
+ import type { ISeriesEpisode, ISeriesItem } from './types';
7
+
8
+ interface ICommenProps {
9
+ data: ISeriesItem;
10
+ currentTime: number;
11
+ duration: number;
12
+ onLikePress: () => void;
13
+ onPlayPausePress: () => void;
14
+ onEpisodesPress: () => void;
15
+ onSharePress?: () => void;
16
+ activeEpisodeIndex: number;
17
+ }
18
+
19
+ interface IReelSeriesOverlayProps extends ICommenProps {
20
+ reel: ISeriesEpisode;
21
+ }
22
+
23
+ const ReelSeriesOverlay: React.FC<IReelSeriesOverlayProps> = ({
24
+ data,
25
+ currentTime,
26
+ duration,
27
+ onLikePress,
28
+ onEpisodesPress,
29
+ onSharePress,
30
+ activeEpisodeIndex,
31
+ }) => {
32
+ return (
33
+ <View style={styles.overlay}>
34
+ {/* Right Side Actions */}
35
+ <View style={styles.rightIcons}>
36
+ <TouchableOpacity
37
+ style={styles.iconBox}
38
+ onPress={onLikePress}
39
+ activeOpacity={0.7}
40
+ >
41
+ <Heart
42
+ size={moderateScale(25)}
43
+ color={data.isLiked ? 'red' : '#fff'}
44
+ fill={data.isLiked ? 'red' : 'none'}
45
+ />
46
+ <Text style={[styles.iconLabel, { color: '#fff' }]}>
47
+ {data.likes}
48
+ </Text>
49
+ </TouchableOpacity>
50
+
51
+ <TouchableOpacity style={styles.iconBox} onPress={onEpisodesPress}>
52
+ <ListVideo color={'#fff'} size={moderateScale(25)} />
53
+ <Text style={[styles.iconLabel, { color: '#fff' }]}>Episodes</Text>
54
+ </TouchableOpacity>
55
+
56
+ <TouchableOpacity style={styles.iconBox} onPress={onSharePress}>
57
+ <Forward color={'#fff'} size={moderateScale(25)} />
58
+ <Text style={[styles.iconLabel, { color: '#fff' }]}>Share</Text>
59
+ </TouchableOpacity>
60
+ </View>
61
+
62
+ {/* Title & Description */}
63
+ <View style={styles.titleBox}>
64
+ <Text style={[styles.title, { color: '#fff' }]}>
65
+ {data.title.length <= 25
66
+ ? data.title
67
+ : data.title.slice(0, 25) + '...'}
68
+ </Text>
69
+ <Text
70
+ numberOfLines={2}
71
+ style={[
72
+ styles.description,
73
+ { color: '#fff', marginTop: 2.5, opacity: 0.9 },
74
+ ]}
75
+ >
76
+ {data.description}
77
+ </Text>
78
+ </View>
79
+
80
+ {/* Episodes Button */}
81
+
82
+ <TouchableOpacity
83
+ style={[styles.episodesRow, { backgroundColor: 'rgba(0,0,0,0.5)' }]}
84
+ onPress={onEpisodesPress}
85
+ >
86
+ <View style={styles.bottomLeft}>
87
+ <ListVideo
88
+ color={'#fff'}
89
+ width={moderateScale(20)}
90
+ height={moderateScale(20)}
91
+ />
92
+ <Text style={[styles.episodes, { color: '#fff' }]}>
93
+ {activeEpisodeIndex + 1} / {data.episodes.length} Episodes
94
+ </Text>
95
+ </View>
96
+ <ChevronRight color={'#fff'} size={moderateScale(22)} />
97
+ </TouchableOpacity>
98
+
99
+ {/* Progress Bar */}
100
+ <View style={styles.progressBar}>
101
+ <View
102
+ style={[
103
+ styles.progressFill,
104
+ {
105
+ width: duration > 0 ? `${(currentTime / duration) * 100}%` : '0%',
106
+ },
107
+ ]}
108
+ />
109
+ {duration > 0 && (
110
+ <View
111
+ style={[
112
+ styles.progressKnob,
113
+ { left: `${(currentTime / duration) * 100}%` },
114
+ ]}
115
+ />
116
+ )}
117
+ </View>
118
+ </View>
119
+ );
120
+ };
121
+
122
+ export default ReelSeriesOverlay;
123
+
124
+ const styles = StyleSheet.create({
125
+ overlay: {
126
+ flex: 1,
127
+ justifyContent: 'flex-end',
128
+ paddingBottom: verticalScale(12),
129
+ paddingHorizontal: moderateScale(12),
130
+ },
131
+ centerPlayPauseButton: {
132
+ position: 'absolute',
133
+ top: '50%',
134
+ left: '50%',
135
+ transform: [{ translateX: -25 }, { translateY: -25 }],
136
+ width: moderateScale(50),
137
+ height: moderateScale(50),
138
+ borderRadius: moderateScale(25),
139
+ justifyContent: 'center',
140
+ alignItems: 'center',
141
+ zIndex: 5,
142
+ },
143
+ rightIcons: {
144
+ position: 'absolute',
145
+ bottom: verticalScale(120),
146
+ right: moderateScale(10),
147
+ alignItems: 'center',
148
+ },
149
+ iconBox: { marginVertical: verticalScale(8), alignItems: 'center' },
150
+ iconLabel: { fontSize: RFValue(10), marginTop: verticalScale(4) },
151
+ titleBox: { marginBottom: verticalScale(10) },
152
+ following: { fontSize: RFValue(10), fontWeight: '500' },
153
+ title: { fontSize: RFValue(13), fontWeight: '500' },
154
+ description: { fontSize: RFValue(10) },
155
+ episodesRow: {
156
+ flexDirection: 'row',
157
+ justifyContent: 'space-between',
158
+ alignItems: 'center',
159
+ borderRadius: moderateScale(8),
160
+ paddingHorizontal: moderateScale(12),
161
+ paddingVertical: verticalScale(8),
162
+ marginBottom: verticalScale(6),
163
+ },
164
+ bottomLeft: { flexDirection: 'row', alignItems: 'center' },
165
+ episodes: { fontSize: RFValue(13), marginLeft: moderateScale(10) },
166
+ progressBar: {
167
+ height: verticalScale(2),
168
+ backgroundColor: 'rgba(255, 255, 255, 0.3)',
169
+ borderRadius: moderateScale(1),
170
+ },
171
+ progressFill: {
172
+ height: '100%',
173
+ backgroundColor: '#fff',
174
+ borderRadius: moderateScale(1),
175
+ },
176
+ progressKnob: {
177
+ position: 'absolute',
178
+ top: -verticalScale(2),
179
+ width: moderateScale(7),
180
+ height: moderateScale(7),
181
+ borderRadius: moderateScale(5),
182
+ backgroundColor: '#fff',
183
+ transform: [{ translateX: -5 }],
184
+ },
185
+ });