@zezosoft/zezo-ott-react-native-ui-kit 1.1.2 → 1.1.3

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 (136) hide show
  1. package/lib/module/components/Auth/QrLogin/QrLogin.js +304 -138
  2. package/lib/module/components/Auth/QrLogin/QrLogin.js.map +1 -1
  3. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js +193 -141
  4. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js.map +1 -1
  5. package/lib/module/components/Content/Card/Category/Category.js +83 -11
  6. package/lib/module/components/Content/Card/Category/Category.js.map +1 -1
  7. package/lib/module/components/Content/Card/NowWatching/NowWatching.js +237 -108
  8. package/lib/module/components/Content/Card/NowWatching/NowWatching.js.map +1 -1
  9. package/lib/module/components/Content/Card/Sliders/Styles/One.js +185 -126
  10. package/lib/module/components/Content/Card/Sliders/Styles/One.js.map +1 -1
  11. package/lib/module/components/Content/Card/Sliders/Styles/Two.js +139 -92
  12. package/lib/module/components/Content/Card/Sliders/Styles/Two.js.map +1 -1
  13. package/lib/module/components/Content/Card/Styles/Five.js +131 -48
  14. package/lib/module/components/Content/Card/Styles/Five.js.map +1 -1
  15. package/lib/module/components/Content/Card/Styles/Four.js +126 -59
  16. package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
  17. package/lib/module/components/Content/Card/Styles/One.js +125 -50
  18. package/lib/module/components/Content/Card/Styles/One.js.map +1 -1
  19. package/lib/module/components/Content/Card/Styles/RotateInOut.js +138 -53
  20. package/lib/module/components/Content/Card/Styles/RotateInOut.js.map +1 -1
  21. package/lib/module/components/Content/Card/Styles/Six.js +207 -115
  22. package/lib/module/components/Content/Card/Styles/Six.js.map +1 -1
  23. package/lib/module/components/Content/Card/Styles/Three.js +134 -79
  24. package/lib/module/components/Content/Card/Styles/Three.js.map +1 -1
  25. package/lib/module/components/Content/Card/Styles/TopTen.js +186 -171
  26. package/lib/module/components/Content/Card/Styles/TopTen.js.map +1 -1
  27. package/lib/module/components/Content/Card/Styles/Two.js +144 -64
  28. package/lib/module/components/Content/Card/Styles/Two.js.map +1 -1
  29. package/lib/module/components/Content/Card/components/AdsPoster.js +162 -0
  30. package/lib/module/components/Content/Card/components/AdsPoster.js.map +1 -0
  31. package/lib/module/components/Content/Card/components/CardPoster.js +120 -136
  32. package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
  33. package/lib/module/components/Content/Card/components/index.js +4 -0
  34. package/lib/module/components/Content/Card/components/index.js.map +1 -0
  35. package/lib/module/components/Content/Content.js +67 -27
  36. package/lib/module/components/Content/Content.js.map +1 -1
  37. package/lib/module/components/Content/Sections.js +32 -11
  38. package/lib/module/components/Content/Sections.js.map +1 -1
  39. package/lib/module/constants/dummySections.js +44 -4
  40. package/lib/module/constants/dummySections.js.map +1 -1
  41. package/lib/module/hooks/Images/index.js +5 -0
  42. package/lib/module/hooks/Images/index.js.map +1 -0
  43. package/lib/module/hooks/Images/useImageLoader.js +168 -0
  44. package/lib/module/hooks/Images/useImageLoader.js.map +1 -0
  45. package/lib/module/hooks/Images/useImageValidation.js +36 -0
  46. package/lib/module/hooks/Images/useImageValidation.js.map +1 -0
  47. package/lib/module/hooks/index.js +3 -0
  48. package/lib/module/hooks/index.js.map +1 -1
  49. package/lib/module/hooks/useAdTracking.js +270 -0
  50. package/lib/module/hooks/useAdTracking.js.map +1 -0
  51. package/lib/module/hooks/useCards.js +164 -0
  52. package/lib/module/hooks/useCards.js.map +1 -0
  53. package/lib/module/hooks/usePaginatedSection.js +11 -6
  54. package/lib/module/hooks/usePaginatedSection.js.map +1 -1
  55. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts +2 -0
  56. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts.map +1 -1
  57. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts.map +1 -1
  58. package/lib/typescript/src/components/Content/Card/Category/Category.d.ts.map +1 -1
  59. package/lib/typescript/src/components/Content/Card/NowWatching/NowWatching.d.ts.map +1 -1
  60. package/lib/typescript/src/components/Content/Card/Sliders/Styles/One.d.ts.map +1 -1
  61. package/lib/typescript/src/components/Content/Card/Sliders/Styles/Two.d.ts.map +1 -1
  62. package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts +13 -1
  63. package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts.map +1 -1
  64. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts +13 -1
  65. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
  66. package/lib/typescript/src/components/Content/Card/Styles/One.d.ts +15 -3
  67. package/lib/typescript/src/components/Content/Card/Styles/One.d.ts.map +1 -1
  68. package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts +13 -1
  69. package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts.map +1 -1
  70. package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts +1 -0
  71. package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts.map +1 -1
  72. package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts +13 -5
  73. package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts.map +1 -1
  74. package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts +1 -0
  75. package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts.map +1 -1
  76. package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts +13 -1
  77. package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts.map +1 -1
  78. package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts +26 -0
  79. package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts.map +1 -0
  80. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts +3 -1
  81. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
  82. package/lib/typescript/src/components/Content/Card/components/index.d.ts +2 -0
  83. package/lib/typescript/src/components/Content/Card/components/index.d.ts.map +1 -0
  84. package/lib/typescript/src/components/Content/Card/index.d.ts +76 -6
  85. package/lib/typescript/src/components/Content/Card/index.d.ts.map +1 -1
  86. package/lib/typescript/src/components/Content/Content.d.ts +4 -3
  87. package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
  88. package/lib/typescript/src/components/Content/Sections.d.ts +20 -6
  89. package/lib/typescript/src/components/Content/Sections.d.ts.map +1 -1
  90. package/lib/typescript/src/constants/dummySections.d.ts +5 -0
  91. package/lib/typescript/src/constants/dummySections.d.ts.map +1 -1
  92. package/lib/typescript/src/hooks/Images/index.d.ts +3 -0
  93. package/lib/typescript/src/hooks/Images/index.d.ts.map +1 -0
  94. package/lib/typescript/src/hooks/Images/useImageLoader.d.ts +36 -0
  95. package/lib/typescript/src/hooks/Images/useImageLoader.d.ts.map +1 -0
  96. package/lib/typescript/src/hooks/Images/useImageValidation.d.ts +17 -0
  97. package/lib/typescript/src/hooks/Images/useImageValidation.d.ts.map +1 -0
  98. package/lib/typescript/src/hooks/index.d.ts +3 -0
  99. package/lib/typescript/src/hooks/index.d.ts.map +1 -1
  100. package/lib/typescript/src/hooks/useAdTracking.d.ts +39 -0
  101. package/lib/typescript/src/hooks/useAdTracking.d.ts.map +1 -0
  102. package/lib/typescript/src/hooks/useCards.d.ts +36 -0
  103. package/lib/typescript/src/hooks/useCards.d.ts.map +1 -0
  104. package/lib/typescript/src/hooks/usePaginatedSection.d.ts +12 -2
  105. package/lib/typescript/src/hooks/usePaginatedSection.d.ts.map +1 -1
  106. package/lib/typescript/src/types/sections/index.d.ts +7 -4
  107. package/lib/typescript/src/types/sections/index.d.ts.map +1 -1
  108. package/package.json +6 -3
  109. package/src/components/Auth/QrLogin/QrLogin.tsx +382 -122
  110. package/src/components/Auth/QrLogin/components/QrViewArea.tsx +291 -197
  111. package/src/components/Content/Card/Category/Category.tsx +95 -8
  112. package/src/components/Content/Card/NowWatching/NowWatching.tsx +281 -136
  113. package/src/components/Content/Card/Sliders/Styles/One.tsx +244 -148
  114. package/src/components/Content/Card/Sliders/Styles/Two.tsx +171 -102
  115. package/src/components/Content/Card/Styles/Five.tsx +161 -62
  116. package/src/components/Content/Card/Styles/Four.tsx +164 -85
  117. package/src/components/Content/Card/Styles/One.tsx +161 -71
  118. package/src/components/Content/Card/Styles/RotateInOut.tsx +157 -60
  119. package/src/components/Content/Card/Styles/Six.tsx +242 -142
  120. package/src/components/Content/Card/Styles/Three.tsx +166 -133
  121. package/src/components/Content/Card/Styles/TopTen.tsx +230 -191
  122. package/src/components/Content/Card/Styles/Two.tsx +182 -79
  123. package/src/components/Content/Card/components/AdsPoster.tsx +202 -0
  124. package/src/components/Content/Card/components/CardPoster.tsx +134 -154
  125. package/src/components/Content/Card/components/index.ts +1 -0
  126. package/src/components/Content/Content.tsx +83 -45
  127. package/src/components/Content/Sections.tsx +51 -10
  128. package/src/constants/dummySections.ts +48 -1
  129. package/src/hooks/Images/index.ts +2 -0
  130. package/src/hooks/Images/useImageLoader.ts +206 -0
  131. package/src/hooks/Images/useImageValidation.ts +36 -0
  132. package/src/hooks/index.ts +3 -0
  133. package/src/hooks/useAdTracking.ts +349 -0
  134. package/src/hooks/useCards.ts +228 -0
  135. package/src/hooks/usePaginatedSection.ts +26 -7
  136. package/src/types/sections/index.ts +7 -4
@@ -13,37 +13,50 @@ import {
13
13
  type ViewStyle,
14
14
  type TextStyle,
15
15
  type AccessibilityProps,
16
- type ListRenderItemInfo,
17
16
  } from 'react-native';
17
+
18
18
  import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
19
19
  import FastImage from 'react-native-fast-image';
20
20
  import { moderateScale, verticalScale } from 'react-native-size-matters';
21
+ import { RFValue } from 'react-native-responsive-fontsize';
22
+
21
23
  import { useInternalTheme } from '../../../../theme/hook/useInternalTheme';
24
+ import type { ITheme, ThemeOverride } from '../../../../theme/themes';
25
+
22
26
  import CardPoster from '../components/CardPoster';
23
27
  import NavigateToMore from '../components/NavigateToMore';
24
- import { usePaginatedSection } from '../../../../hooks/usePaginatedSection';
28
+ import { AdsPoster } from '../components';
29
+
25
30
  import type {
31
+ IAdItem,
26
32
  IGetSectionData,
27
33
  ISectionContent,
28
34
  MoreFetchData,
29
35
  } from '../../../../types';
30
- import type { ITheme, ThemeOverride } from '../../../../theme/themes';
31
- import { RFValue } from 'react-native-responsive-fontsize';
32
- import type { IContentData } from '@zezosoft/zezo-ott-api-client';
36
+
37
+ import type { IContentData, IServeAd } from '@zezosoft/zezo-ott-api-client';
38
+ import { useCards } from '../../../../hooks';
33
39
 
34
40
  // Constants
35
41
  const DEFAULT_ITEM_WIDTH = moderateScale(105);
36
42
  const DEFAULT_ITEM_HEIGHT = moderateScale(160);
37
43
  const DEFAULT_BORDER_RADIUS = moderateScale(6);
38
44
  const DEFAULT_SKELETON_COUNT = 5;
45
+ const END_REACHED_THRESHOLD = 0.5;
46
+ const SKELETON_TITLE_WIDTH = moderateScale(100);
47
+ const SKELETON_TITLE_HEIGHT = verticalScale(14);
48
+ const SKELETON_TITLE_BORDER_RADIUS = moderateScale(4);
49
+ const SKELETON_ITEM_MARGIN = moderateScale(12);
50
+ const ITEM_ACTIVE_OPACITY = 0.8;
39
51
 
52
+ // Types
40
53
  type MovieCardProps = {
41
54
  title: string;
42
55
  section_id: string;
43
56
  type: IGetSectionData['type'];
44
57
  data: ISectionContent | null;
45
58
  moreFetchData?: MoreFetchData<IContentData>;
46
- onPressItem?: (item: IContentData) => void;
59
+ onPressItem?: (item: IContentData | IAdItem) => void;
47
60
  onPressMore?: (params: {
48
61
  section_id: IGetSectionData['_id'];
49
62
  name: IGetSectionData['name'];
@@ -59,24 +72,36 @@ type MovieCardProps = {
59
72
  skeletonCount?: number;
60
73
  containerStyle?: StyleProp<ViewStyle>;
61
74
  titleStyle?: StyleProp<TextStyle>;
75
+ paginationSkeletonCount?: number;
62
76
  itemStyle?: StyleProp<ViewStyle>;
63
77
  isLoading?: boolean;
64
78
  theme?: ThemeOverride;
79
+ onDisplayAds?: (ad: IServeAd) => void;
80
+ screenDimensions?: { width: number; height: number };
81
+ viewportOffsets?: {
82
+ top: number;
83
+ bottom: number;
84
+ left: number;
85
+ right: number;
86
+ };
65
87
  } & AccessibilityProps;
66
88
 
89
+ // Main Component
67
90
  const MovieCard: React.FC<MovieCardProps> = ({
68
91
  title,
69
92
  section_id,
70
93
  type,
71
- data: initialData,
94
+ data: externalData,
72
95
  moreFetchData,
73
- onPressMore,
74
96
  onPressItem,
97
+ onPressMore,
98
+
75
99
  renderItemImage,
76
100
  itemWidth = DEFAULT_ITEM_WIDTH,
77
101
  itemHeight = DEFAULT_ITEM_HEIGHT,
78
102
  borderRadius = DEFAULT_BORDER_RADIUS,
79
103
  skeletonCount = DEFAULT_SKELETON_COUNT,
104
+ paginationSkeletonCount,
80
105
  containerStyle,
81
106
  titleStyle,
82
107
  itemStyle,
@@ -84,30 +109,46 @@ const MovieCard: React.FC<MovieCardProps> = ({
84
109
  theme,
85
110
  accessibilityLabel,
86
111
  accessibilityHint,
112
+ onDisplayAds,
113
+ screenDimensions,
114
+ viewportOffsets,
87
115
  }) => {
88
- const flatListRef = useRef<FlatList<IContentData>>(null);
116
+ // Refs
117
+ const flatListRef = useRef<FlatList<IContentData | IAdItem>>(null);
118
+ const containerRef = useRef<View>(null);
89
119
  const onEndReachedCalledDuringMomentum = useRef(false);
120
+
121
+ // Theme
90
122
  const { theme: appliedTheme } = useInternalTheme(theme);
91
123
 
124
+ // Styles
92
125
  const styles = useMemo(
93
126
  () => getStyles(appliedTheme, itemWidth, itemHeight, borderRadius),
94
127
  [appliedTheme, itemWidth, itemHeight, borderRadius]
95
128
  );
96
129
 
130
+ // Data Management
97
131
  const {
98
- data,
132
+ listData,
99
133
  pagination,
100
- loading: isPaginating,
101
- loadMoreData,
102
- } = usePaginatedSection(
103
- section_id,
104
- moreFetchData,
105
- initialData?.data || [],
106
- isLoading
107
- );
134
+ loadMore,
135
+ isEmpty,
136
+ isPaging: isPaginating,
137
+ } = useCards({
138
+ sectionId: section_id,
139
+ data: externalData,
140
+ fetchMore: moreFetchData,
141
+ loading: isLoading,
142
+ initialSkeleton: skeletonCount,
143
+ pagingSkeleton: paginationSkeletonCount,
144
+ adsRender: true,
145
+ });
108
146
 
147
+ // Event Handlers
109
148
  const handleItemPress = useCallback(
110
- (item: IContentData) => onPressItem?.(item),
149
+ (item: IContentData | IAdItem) => {
150
+ onPressItem?.(item);
151
+ },
111
152
  [onPressItem]
112
153
  );
113
154
 
@@ -122,31 +163,68 @@ const MovieCard: React.FC<MovieCardProps> = ({
122
163
  pagination?.nextPage
123
164
  ) {
124
165
  onEndReachedCalledDuringMomentum.current = true;
125
- loadMoreData(pagination.nextPage);
166
+ loadMore(pagination.nextPage);
126
167
  }
127
- }, [loadMoreData, pagination]);
168
+ }, [pagination, loadMore]);
169
+
170
+ const handleMomentumScrollBegin = useCallback(() => {
171
+ onEndReachedCalledDuringMomentum.current = false;
172
+ }, []);
128
173
 
174
+ // Render Functions
129
175
  const renderItem = useCallback(
130
- ({ item, index }: ListRenderItemInfo<IContentData>) => {
176
+ ({ item, index }: { item: IContentData | IAdItem; index: number }) => {
177
+ // Handle ads
178
+ if ('type' in item && item.type === 'ads') {
179
+ const adItem = item as IAdItem;
180
+ return (
181
+ <View
182
+ key={`ad-${adItem.tracking?.impression || index}`}
183
+ style={[styles.item, itemStyle]}
184
+ >
185
+ <AdsPoster
186
+ ad={adItem}
187
+ theme={appliedTheme}
188
+ isLoading={isLoading}
189
+ containerStyle={{ width: itemWidth, height: itemHeight }}
190
+ imageStyle={styles.image}
191
+ onPress={() => handleItemPress(adItem)}
192
+ borderRadius={borderRadius}
193
+ onDisplayAds={onDisplayAds}
194
+ screenDimensions={screenDimensions}
195
+ viewportOffsets={viewportOffsets}
196
+ />
197
+ </View>
198
+ );
199
+ }
200
+
201
+ // Handle content items
202
+ const contentItem = item as IContentData;
203
+ const isSkeleton =
204
+ contentItem._id?.startsWith?.('pagination-skeleton') ?? false;
205
+
131
206
  return (
132
207
  <TouchableOpacity
133
- key={item._id}
208
+ key={contentItem._id}
134
209
  style={[styles.item, itemStyle]}
135
- onPress={() => handleItemPress(item)}
136
- activeOpacity={0.8}
210
+ activeOpacity={ITEM_ACTIVE_OPACITY}
211
+ onPress={() => {
212
+ if (!isSkeleton && !isLoading) {
213
+ handleItemPress(contentItem);
214
+ }
215
+ }}
137
216
  >
138
217
  {renderItemImage ? (
139
218
  renderItemImage({ item, index })
140
219
  ) : (
141
220
  <CardPoster
142
- key={item._id}
143
- content_offering_type={item.content_offering_type}
144
- posterUri={item.poster}
221
+ posterUri={contentItem.poster}
222
+ content_offering_type={contentItem.content_offering_type}
145
223
  theme={appliedTheme}
146
224
  borderRadius={borderRadius}
147
225
  posterWrapperStyle={styles.image}
148
226
  resizeMode={FastImage.resizeMode.cover}
149
- isLoading={isLoading}
227
+ isLoading={isSkeleton || isLoading}
150
228
  />
151
229
  )}
152
230
  </TouchableOpacity>
@@ -160,50 +238,67 @@ const MovieCard: React.FC<MovieCardProps> = ({
160
238
  appliedTheme,
161
239
  borderRadius,
162
240
  isLoading,
241
+ itemWidth,
242
+ itemHeight,
243
+ onDisplayAds,
244
+ screenDimensions,
245
+ viewportOffsets,
163
246
  handleItemPress,
164
247
  ]
165
248
  );
166
249
 
167
- const renderSkeletonItem = ({ index }: { index: number }) => (
168
- <SkeletonPlaceholder
169
- key={`skeleton-${index}`}
170
- highlightColor={appliedTheme.colors.skeletonHighlightColor}
171
- backgroundColor={appliedTheme.colors.skeletonBaseColor}
172
- >
173
- <SkeletonPlaceholder.Item
174
- width={itemWidth}
175
- height={itemHeight}
176
- borderRadius={borderRadius}
177
- marginLeft={index === 0 ? moderateScale(12) : 0}
178
- marginRight={moderateScale(12)}
179
- />
180
- </SkeletonPlaceholder>
250
+ const renderSkeletonItem = useCallback(
251
+ ({ index }: { index: number }) => (
252
+ <SkeletonPlaceholder
253
+ key={`skeleton-${index}`}
254
+ highlightColor={appliedTheme.colors.skeletonHighlightColor}
255
+ backgroundColor={appliedTheme.colors.skeletonBaseColor}
256
+ >
257
+ <SkeletonPlaceholder.Item
258
+ width={itemWidth}
259
+ height={itemHeight}
260
+ borderRadius={borderRadius}
261
+ marginLeft={index === 0 ? SKELETON_ITEM_MARGIN : 0}
262
+ marginRight={SKELETON_ITEM_MARGIN}
263
+ />
264
+ </SkeletonPlaceholder>
265
+ ),
266
+ [appliedTheme, itemWidth, itemHeight, borderRadius]
181
267
  );
182
- if (!initialData) {
183
- return null;
184
- }
185
- if (!isLoading && data.length === 0) return null;
186
268
 
269
+ const keyExtractor = useCallback(
270
+ (item: IContentData | IAdItem, index: number) => {
271
+ if ('type' in item && item.type === 'ads') {
272
+ return `ad-${(item as IAdItem).tracking?.impression || index}`;
273
+ }
274
+ return (item as IContentData)._id || `item-${index}`;
275
+ },
276
+ []
277
+ );
278
+
279
+ // Early Returns
280
+ if (!externalData) return null;
281
+ if (!isLoading && listData.length === 0 && !isEmpty) return null;
282
+
283
+ // Loading State
187
284
  if (isLoading) {
188
285
  return (
189
- <View
190
- style={[styles.root, containerStyle]}
191
- testID={`movie-card-skeleton-${section_id}`}
192
- >
286
+ <View style={[styles.root, containerStyle]}>
193
287
  <SkeletonPlaceholder
194
288
  highlightColor={appliedTheme.colors.skeletonHighlightColor}
195
289
  backgroundColor={appliedTheme.colors.skeletonBaseColor}
196
290
  >
197
291
  <SkeletonPlaceholder.Item
198
- width={moderateScale(100)}
199
- height={verticalScale(14)}
200
- borderRadius={moderateScale(4)}
201
- marginLeft={moderateScale(12)}
292
+ width={SKELETON_TITLE_WIDTH}
293
+ height={SKELETON_TITLE_HEIGHT}
294
+ borderRadius={SKELETON_TITLE_BORDER_RADIUS}
295
+ marginLeft={SKELETON_ITEM_MARGIN}
202
296
  marginBottom={verticalScale(6)}
203
297
  />
204
298
  </SkeletonPlaceholder>
299
+
205
300
  <FlatList
206
- data={Array.from({ length: skeletonCount }, () => null)}
301
+ data={Array.from({ length: skeletonCount })}
207
302
  horizontal
208
303
  keyExtractor={(_, index) => `skeleton-${index}`}
209
304
  renderItem={renderSkeletonItem}
@@ -214,12 +309,14 @@ const MovieCard: React.FC<MovieCardProps> = ({
214
309
  );
215
310
  }
216
311
 
312
+ // Main Render
217
313
  return (
218
314
  <View
315
+ ref={containerRef}
219
316
  style={[styles.root, containerStyle]}
220
- testID={`movie-card-${section_id}`}
221
317
  accessibilityLabel={accessibilityLabel || `Movie section: ${title}`}
222
- accessibilityHint={accessibilityHint || 'Scroll to view movies'}
318
+ accessibilityHint={accessibilityHint || 'Scroll to view items'}
319
+ testID={`movie-card-${section_id}`}
223
320
  >
224
321
  <NavigateToMore
225
322
  title={title}
@@ -232,23 +329,18 @@ const MovieCard: React.FC<MovieCardProps> = ({
232
329
  containerStyle={styles.navigateToMoreContainer}
233
330
  showAllProps={{ iconColor: appliedTheme.colors.textPrimary, theme }}
234
331
  />
332
+
235
333
  <FlatList
236
334
  ref={flatListRef}
237
- data={data}
335
+ data={listData}
238
336
  horizontal
239
- keyExtractor={(item, index) => (item._id ? item._id : `item-${index}`)}
337
+ keyExtractor={keyExtractor}
240
338
  renderItem={renderItem}
241
339
  showsHorizontalScrollIndicator={false}
242
340
  contentContainerStyle={styles.listContent}
243
- initialNumToRender={5}
244
341
  onEndReached={handleEndReached}
245
- onEndReachedThreshold={0.5}
246
- onScrollBeginDrag={() => {
247
- onEndReachedCalledDuringMomentum.current = false;
248
- }}
249
- onMomentumScrollBegin={() => {
250
- onEndReachedCalledDuringMomentum.current = false;
251
- }}
342
+ onEndReachedThreshold={END_REACHED_THRESHOLD}
343
+ onMomentumScrollBegin={handleMomentumScrollBegin}
252
344
  ListFooterComponent={
253
345
  isPaginating ? renderSkeletonItem({ index: 0 }) : null
254
346
  }
@@ -257,6 +349,7 @@ const MovieCard: React.FC<MovieCardProps> = ({
257
349
  );
258
350
  };
259
351
 
352
+ // Styles
260
353
  const getStyles = (
261
354
  theme: ITheme,
262
355
  width: number,
@@ -276,9 +369,6 @@ const getStyles = (
276
369
  borderRadius: radius,
277
370
  backgroundColor: theme.colors.surfaceVariant,
278
371
  },
279
- imageWrapper: {
280
- position: 'relative',
281
- },
282
372
  navigateToMoreContainer: {
283
373
  paddingHorizontal: moderateScale(10),
284
374
  marginBottom: verticalScale(8),