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

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 (265) hide show
  1. package/README.md +1 -1
  2. package/lib/module/assets/animations/Failed.json +2103 -0
  3. package/lib/module/assets/animations/Pending.json +522 -0
  4. package/lib/module/assets/animations/Successful.json +2289 -0
  5. package/lib/module/assets/animations/heart.json +788 -0
  6. package/lib/module/components/Alert/AlertDialog.js +208 -0
  7. package/lib/module/components/Alert/AlertDialog.js.map +1 -0
  8. package/lib/module/components/Alert/index.js +1 -0
  9. package/lib/module/components/Alert/index.js.map +1 -1
  10. package/lib/module/components/Auth/AuthProvider/AuthProvider.js +270 -0
  11. package/lib/module/components/Auth/AuthProvider/AuthProvider.js.map +1 -0
  12. package/lib/module/components/Auth/QrLogin/QrLogin.js +267 -0
  13. package/lib/module/components/Auth/QrLogin/QrLogin.js.map +1 -0
  14. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js +178 -0
  15. package/lib/module/components/Auth/QrLogin/components/QrViewArea.js.map +1 -0
  16. package/lib/module/components/Auth/SplashScreen/SplashScreen.js +63 -65
  17. package/lib/module/components/Auth/SplashScreen/SplashScreen.js.map +1 -1
  18. package/lib/module/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.js +82 -41
  19. package/lib/module/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.js.map +1 -1
  20. package/lib/module/components/Auth/index.js +5 -1
  21. package/lib/module/components/Auth/index.js.map +1 -1
  22. package/lib/module/components/BackgroundLayout/BackgroundLayout.js +3 -3
  23. package/lib/module/components/BackgroundLayout/BackgroundLayout.js.map +1 -1
  24. package/lib/module/components/Button/SecondaryBtn.js +91 -0
  25. package/lib/module/components/Button/SecondaryBtn.js.map +1 -0
  26. package/lib/module/components/Button/index.js +2 -0
  27. package/lib/module/components/Button/index.js.map +1 -1
  28. package/lib/module/components/Content/Card/NowWatching/NowWatching.js +6 -3
  29. package/lib/module/components/Content/Card/NowWatching/NowWatching.js.map +1 -1
  30. package/lib/module/components/Content/Card/Sliders/Styles/One.js +4 -1
  31. package/lib/module/components/Content/Card/Sliders/Styles/One.js.map +1 -1
  32. package/lib/module/components/Content/Card/Sliders/Styles/Two.js +4 -1
  33. package/lib/module/components/Content/Card/Sliders/Styles/Two.js.map +1 -1
  34. package/lib/module/components/Content/Card/Styles/Five.js +1 -0
  35. package/lib/module/components/Content/Card/Styles/Five.js.map +1 -1
  36. package/lib/module/components/Content/Card/Styles/Four.js +1 -0
  37. package/lib/module/components/Content/Card/Styles/Four.js.map +1 -1
  38. package/lib/module/components/Content/Card/Styles/One.js +7 -3
  39. package/lib/module/components/Content/Card/Styles/One.js.map +1 -1
  40. package/lib/module/components/Content/Card/Styles/RotateInOut.js +1 -0
  41. package/lib/module/components/Content/Card/Styles/RotateInOut.js.map +1 -1
  42. package/lib/module/components/Content/Card/Styles/Six.js +4 -1
  43. package/lib/module/components/Content/Card/Styles/Six.js.map +1 -1
  44. package/lib/module/components/Content/Card/Styles/Three.js +1 -0
  45. package/lib/module/components/Content/Card/Styles/Three.js.map +1 -1
  46. package/lib/module/components/Content/Card/Styles/TopTen.js +1 -0
  47. package/lib/module/components/Content/Card/Styles/TopTen.js.map +1 -1
  48. package/lib/module/components/Content/Card/Styles/Two.js +1 -0
  49. package/lib/module/components/Content/Card/Styles/Two.js.map +1 -1
  50. package/lib/module/components/Content/Card/components/CardPoster.js +12 -28
  51. package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
  52. package/lib/module/components/Content/Card/components/RentOrBuyIcon.js +116 -0
  53. package/lib/module/components/Content/Card/components/RentOrBuyIcon.js.map +1 -0
  54. package/lib/module/components/Content/Card/components/ThumbnailCard.js +1 -2
  55. package/lib/module/components/Content/Card/components/ThumbnailCard.js.map +1 -1
  56. package/lib/module/components/ContentView/ContentView.js +1 -0
  57. package/lib/module/components/ContentView/ContentView.js.map +1 -1
  58. package/lib/module/components/ContentView/MoreContentList.js +1 -0
  59. package/lib/module/components/ContentView/MoreContentList.js.map +1 -1
  60. package/lib/module/components/ContentView/components/EpisodeCard.js +6 -10
  61. package/lib/module/components/ContentView/components/EpisodeCard.js.map +1 -1
  62. package/lib/module/components/ContentView/components/HeroBanner.js +17 -5
  63. package/lib/module/components/ContentView/components/HeroBanner.js.map +1 -1
  64. package/lib/module/components/Headers/AppHeader.js +1 -1
  65. package/lib/module/components/Headers/AppHeader.js.map +1 -1
  66. package/lib/module/components/Headers/One.js +1 -1
  67. package/lib/module/components/Headers/One.js.map +1 -1
  68. package/lib/module/components/Headers/Two.js +1 -1
  69. package/lib/module/components/Headers/Two.js.map +1 -1
  70. package/lib/module/components/Logo/Logo.js +5 -5
  71. package/lib/module/components/Logo/Logo.js.map +1 -1
  72. package/lib/module/components/Reels/ReelsSeries/Model/Episodes.js +110 -0
  73. package/lib/module/components/Reels/ReelsSeries/Model/Episodes.js.map +1 -0
  74. package/lib/module/components/Reels/ReelsSeries/Model/Synopsis.js +212 -0
  75. package/lib/module/components/Reels/ReelsSeries/Model/Synopsis.js.map +1 -0
  76. package/lib/module/components/Reels/ReelsSeries/ReelSeriesDetailsModal.js +182 -0
  77. package/lib/module/components/Reels/ReelsSeries/ReelSeriesDetailsModal.js.map +1 -0
  78. package/lib/module/components/Reels/ReelsSeries/ReelSeriesOverlay.js +203 -0
  79. package/lib/module/components/Reels/ReelsSeries/ReelSeriesOverlay.js.map +1 -0
  80. package/lib/module/components/Reels/ReelsSeries/ReelsSeries.js +121 -0
  81. package/lib/module/components/Reels/ReelsSeries/ReelsSeries.js.map +1 -0
  82. package/lib/module/components/Reels/ReelsSeries/ReelsSeriesItem.js +290 -0
  83. package/lib/module/components/Reels/ReelsSeries/ReelsSeriesItem.js.map +1 -0
  84. package/lib/module/components/Reels/ReelsSeries/types.js +2 -0
  85. package/lib/module/components/Reels/ReelsSeries/types.js.map +1 -0
  86. package/lib/module/components/Reels/index.js +11 -0
  87. package/lib/module/components/Reels/index.js.map +1 -0
  88. package/lib/module/components/Subscription/SubOne.js +2 -2
  89. package/lib/module/components/Subscription/SubOne.js.map +1 -1
  90. package/lib/module/components/User/DeviceSessions/DeviceSessions.js +8 -0
  91. package/lib/module/components/User/DeviceSessions/DeviceSessions.js.map +1 -1
  92. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js +255 -0
  93. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js.map +1 -0
  94. package/lib/module/components/User/WatchHistory/WatchHistory.js +1 -0
  95. package/lib/module/components/User/WatchHistory/WatchHistory.js.map +1 -1
  96. package/lib/module/components/User/WatchLater/WatchLater.js +1 -0
  97. package/lib/module/components/User/WatchLater/WatchLater.js.map +1 -1
  98. package/lib/module/components/User/components/UserAvatar.js +35 -8
  99. package/lib/module/components/User/components/UserAvatar.js.map +1 -1
  100. package/lib/module/components/User/components/UserSection.js +8 -13
  101. package/lib/module/components/User/components/UserSection.js.map +1 -1
  102. package/lib/module/components/User/index.js +2 -1
  103. package/lib/module/components/User/index.js.map +1 -1
  104. package/lib/module/components/index.js +1 -0
  105. package/lib/module/components/index.js.map +1 -1
  106. package/lib/module/hooks/useSplashCache.js +117 -0
  107. package/lib/module/hooks/useSplashCache.js.map +1 -0
  108. package/lib/module/store/RecentSearchesStore.js +0 -1
  109. package/lib/module/store/RecentSearchesStore.js.map +1 -1
  110. package/lib/module/theme/ThemeProvider.js +13 -10
  111. package/lib/module/theme/ThemeProvider.js.map +1 -1
  112. package/lib/module/theme/themes.js +2 -0
  113. package/lib/module/theme/themes.js.map +1 -1
  114. package/lib/module/utils/Formater.js +17 -0
  115. package/lib/module/utils/Formater.js.map +1 -0
  116. package/lib/typescript/src/components/Alert/AlertDialog.d.ts +18 -0
  117. package/lib/typescript/src/components/Alert/AlertDialog.d.ts.map +1 -0
  118. package/lib/typescript/src/components/Alert/index.d.ts +1 -0
  119. package/lib/typescript/src/components/Alert/index.d.ts.map +1 -1
  120. package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts +35 -0
  121. package/lib/typescript/src/components/Auth/AuthProvider/AuthProvider.d.ts.map +1 -0
  122. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts +32 -0
  123. package/lib/typescript/src/components/Auth/QrLogin/QrLogin.d.ts.map +1 -0
  124. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts +15 -0
  125. package/lib/typescript/src/components/Auth/QrLogin/components/QrViewArea.d.ts.map +1 -0
  126. package/lib/typescript/src/components/Auth/SplashScreen/SplashScreen.d.ts +4 -3
  127. package/lib/typescript/src/components/Auth/SplashScreen/SplashScreen.d.ts.map +1 -1
  128. package/lib/typescript/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.d.ts +1 -1
  129. package/lib/typescript/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.d.ts.map +1 -1
  130. package/lib/typescript/src/components/Auth/index.d.ts +3 -0
  131. package/lib/typescript/src/components/Auth/index.d.ts.map +1 -1
  132. package/lib/typescript/src/components/BackgroundLayout/BackgroundLayout.d.ts.map +1 -1
  133. package/lib/typescript/src/components/Button/SecondaryBtn.d.ts +21 -0
  134. package/lib/typescript/src/components/Button/SecondaryBtn.d.ts.map +1 -0
  135. package/lib/typescript/src/components/Button/index.d.ts +11 -0
  136. package/lib/typescript/src/components/Button/index.d.ts.map +1 -1
  137. package/lib/typescript/src/components/Content/Card/NowWatching/NowWatching.d.ts.map +1 -1
  138. package/lib/typescript/src/components/Content/Card/Sliders/Styles/One.d.ts.map +1 -1
  139. package/lib/typescript/src/components/Content/Card/Sliders/Styles/Two.d.ts.map +1 -1
  140. package/lib/typescript/src/components/Content/Card/Styles/Five.d.ts.map +1 -1
  141. package/lib/typescript/src/components/Content/Card/Styles/Four.d.ts.map +1 -1
  142. package/lib/typescript/src/components/Content/Card/Styles/One.d.ts.map +1 -1
  143. package/lib/typescript/src/components/Content/Card/Styles/RotateInOut.d.ts.map +1 -1
  144. package/lib/typescript/src/components/Content/Card/Styles/Six.d.ts.map +1 -1
  145. package/lib/typescript/src/components/Content/Card/Styles/Three.d.ts.map +1 -1
  146. package/lib/typescript/src/components/Content/Card/Styles/TopTen.d.ts.map +1 -1
  147. package/lib/typescript/src/components/Content/Card/Styles/Two.d.ts.map +1 -1
  148. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts +4 -2
  149. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
  150. package/lib/typescript/src/components/Content/Card/components/RentOrBuyIcon.d.ts +14 -0
  151. package/lib/typescript/src/components/Content/Card/components/RentOrBuyIcon.d.ts.map +1 -0
  152. package/lib/typescript/src/components/ContentView/ContentView.d.ts.map +1 -1
  153. package/lib/typescript/src/components/ContentView/MoreContentList.d.ts.map +1 -1
  154. package/lib/typescript/src/components/ContentView/components/EpisodeCard.d.ts.map +1 -1
  155. package/lib/typescript/src/components/ContentView/components/HeroBanner.d.ts +1 -1
  156. package/lib/typescript/src/components/ContentView/components/HeroBanner.d.ts.map +1 -1
  157. package/lib/typescript/src/components/Logo/Logo.d.ts.map +1 -1
  158. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Episodes.d.ts +12 -0
  159. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Episodes.d.ts.map +1 -0
  160. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Synopsis.d.ts +9 -0
  161. package/lib/typescript/src/components/Reels/ReelsSeries/Model/Synopsis.d.ts.map +1 -0
  162. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.d.ts +13 -0
  163. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.d.ts.map +1 -0
  164. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesOverlay.d.ts +18 -0
  165. package/lib/typescript/src/components/Reels/ReelsSeries/ReelSeriesOverlay.d.ts.map +1 -0
  166. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeries.d.ts +15 -0
  167. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeries.d.ts.map +1 -0
  168. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeriesItem.d.ts +18 -0
  169. package/lib/typescript/src/components/Reels/ReelsSeries/ReelsSeriesItem.d.ts.map +1 -0
  170. package/lib/typescript/src/components/Reels/ReelsSeries/types.d.ts +24 -0
  171. package/lib/typescript/src/components/Reels/ReelsSeries/types.d.ts.map +1 -0
  172. package/lib/typescript/src/components/Reels/index.d.ts +8 -0
  173. package/lib/typescript/src/components/Reels/index.d.ts.map +1 -0
  174. package/lib/typescript/src/components/Subscription/SubOne.d.ts.map +1 -1
  175. package/lib/typescript/src/components/User/DeviceSessions/DeviceSessions.d.ts +1 -0
  176. package/lib/typescript/src/components/User/DeviceSessions/DeviceSessions.d.ts.map +1 -1
  177. package/lib/typescript/src/components/User/ProfileUpdate/ProfileUpdate.d.ts +27 -0
  178. package/lib/typescript/src/components/User/ProfileUpdate/ProfileUpdate.d.ts.map +1 -0
  179. package/lib/typescript/src/components/User/WatchHistory/WatchHistory.d.ts.map +1 -1
  180. package/lib/typescript/src/components/User/WatchLater/WatchLater.d.ts.map +1 -1
  181. package/lib/typescript/src/components/User/components/UserAvatar.d.ts +4 -0
  182. package/lib/typescript/src/components/User/components/UserAvatar.d.ts.map +1 -1
  183. package/lib/typescript/src/components/User/components/UserSection.d.ts.map +1 -1
  184. package/lib/typescript/src/components/User/index.d.ts +2 -1
  185. package/lib/typescript/src/components/User/index.d.ts.map +1 -1
  186. package/lib/typescript/src/components/index.d.ts +1 -0
  187. package/lib/typescript/src/components/index.d.ts.map +1 -1
  188. package/lib/typescript/src/hooks/useSplashCache.d.ts +22 -0
  189. package/lib/typescript/src/hooks/useSplashCache.d.ts.map +1 -0
  190. package/lib/typescript/src/store/RecentSearchesStore.d.ts.map +1 -1
  191. package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -1
  192. package/lib/typescript/src/theme/themes.d.ts +1 -0
  193. package/lib/typescript/src/theme/themes.d.ts.map +1 -1
  194. package/lib/typescript/src/types/content/content-view.types.d.ts +1 -0
  195. package/lib/typescript/src/types/content/content-view.types.d.ts.map +1 -1
  196. package/lib/typescript/src/utils/Formater.d.ts +2 -0
  197. package/lib/typescript/src/utils/Formater.d.ts.map +1 -0
  198. package/package.json +13 -5
  199. package/src/assets/animations/Failed.json +2103 -0
  200. package/src/assets/animations/Pending.json +522 -0
  201. package/src/assets/animations/Successful.json +2289 -0
  202. package/src/assets/animations/heart.json +788 -0
  203. package/src/components/Alert/AlertDialog.tsx +247 -0
  204. package/src/components/Alert/index.ts +1 -0
  205. package/src/components/Auth/AuthProvider/AuthProvider.tsx +344 -0
  206. package/src/components/Auth/QrLogin/QrLogin.tsx +306 -0
  207. package/src/components/Auth/QrLogin/components/QrViewArea.tsx +213 -0
  208. package/src/components/Auth/SplashScreen/SplashScreen.tsx +89 -80
  209. package/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.tsx +90 -40
  210. package/src/components/Auth/index.ts +4 -0
  211. package/src/components/BackgroundLayout/BackgroundLayout.tsx +3 -3
  212. package/src/components/Button/SecondaryBtn.tsx +116 -0
  213. package/src/components/Button/index.ts +2 -0
  214. package/src/components/Content/Card/NowWatching/NowWatching.tsx +4 -0
  215. package/src/components/Content/Card/Sliders/Styles/One.tsx +2 -0
  216. package/src/components/Content/Card/Sliders/Styles/Two.tsx +2 -0
  217. package/src/components/Content/Card/Styles/Five.tsx +1 -0
  218. package/src/components/Content/Card/Styles/Four.tsx +1 -0
  219. package/src/components/Content/Card/Styles/One.tsx +7 -1
  220. package/src/components/Content/Card/Styles/RotateInOut.tsx +1 -0
  221. package/src/components/Content/Card/Styles/Six.tsx +2 -0
  222. package/src/components/Content/Card/Styles/Three.tsx +1 -0
  223. package/src/components/Content/Card/Styles/TopTen.tsx +1 -0
  224. package/src/components/Content/Card/Styles/Two.tsx +1 -0
  225. package/src/components/Content/Card/components/CardPoster.tsx +23 -51
  226. package/src/components/Content/Card/components/RentOrBuyIcon.tsx +109 -0
  227. package/src/components/Content/Card/components/ThumbnailCard.tsx +1 -2
  228. package/src/components/ContentView/ContentView.tsx +1 -0
  229. package/src/components/ContentView/MoreContentList.tsx +1 -0
  230. package/src/components/ContentView/components/EpisodeCard.tsx +4 -9
  231. package/src/components/ContentView/components/HeroBanner.tsx +16 -0
  232. package/src/components/Headers/AppHeader.tsx +1 -1
  233. package/src/components/Headers/One.tsx +1 -1
  234. package/src/components/Headers/Two.tsx +1 -1
  235. package/src/components/Logo/Logo.tsx +5 -7
  236. package/src/components/Reels/ReelsSeries/Model/Episodes.tsx +133 -0
  237. package/src/components/Reels/ReelsSeries/Model/Synopsis.tsx +242 -0
  238. package/src/components/Reels/ReelsSeries/ReelSeriesDetailsModal.tsx +209 -0
  239. package/src/components/Reels/ReelsSeries/ReelSeriesOverlay.tsx +185 -0
  240. package/src/components/Reels/ReelsSeries/ReelsSeries.tsx +163 -0
  241. package/src/components/Reels/ReelsSeries/ReelsSeriesItem.tsx +333 -0
  242. package/src/components/Reels/ReelsSeries/types.ts +27 -0
  243. package/src/components/Reels/index.ts +8 -0
  244. package/src/components/Subscription/SubOne.tsx +4 -2
  245. package/src/components/User/DeviceSessions/DeviceSessions.tsx +11 -0
  246. package/src/components/User/ProfileUpdate/ProfileUpdate.tsx +263 -0
  247. package/src/components/User/WatchHistory/WatchHistory.tsx +1 -0
  248. package/src/components/User/WatchLater/WatchLater.tsx +1 -0
  249. package/src/components/User/components/UserAvatar.tsx +36 -3
  250. package/src/components/User/components/UserSection.tsx +10 -13
  251. package/src/components/User/index.ts +3 -1
  252. package/src/components/index.ts +1 -0
  253. package/src/hooks/useSplashCache.ts +166 -0
  254. package/src/store/RecentSearchesStore.ts +0 -1
  255. package/src/theme/ThemeProvider.tsx +12 -9
  256. package/src/theme/themes.ts +3 -0
  257. package/src/types/content/content-view.types.ts +1 -0
  258. package/src/utils/Formater.ts +14 -0
  259. package/lib/module/hooks/useInitSplashCacheSync.js +0 -116
  260. package/lib/module/hooks/useInitSplashCacheSync.js.map +0 -1
  261. package/lib/typescript/src/hooks/useInitSplashCacheSync.d.ts +0 -22
  262. package/lib/typescript/src/hooks/useInitSplashCacheSync.d.ts.map +0 -1
  263. package/src/hooks/useInitSplashCacheSync.ts +0 -174
  264. /package/lib/module/assets/{img → svg}/h.svg +0 -0
  265. /package/src/assets/{img → svg}/h.svg +0 -0
@@ -0,0 +1,163 @@
1
+ import React, { useState, useCallback, useRef, useMemo } from 'react';
2
+ import {
3
+ FlatList,
4
+ Dimensions,
5
+ StyleSheet,
6
+ View,
7
+ TouchableOpacity,
8
+ type ViewToken,
9
+ } from 'react-native';
10
+ import { debounce } from 'lodash';
11
+ import ReelsSeriesItem from './ReelsSeriesItem';
12
+ import { verticalScale } from 'react-native-size-matters';
13
+ import { Search } from 'lucide-react-native';
14
+ import type { ISeriesEpisode, ISeriesItem } from './types';
15
+
16
+ const { height } = Dimensions.get('window');
17
+ const TAB_BAR_HEIGHT = verticalScale(65);
18
+ const SCREEN_HEIGHT = height - TAB_BAR_HEIGHT;
19
+
20
+ type ReelsProps = {
21
+ data: ISeriesItem;
22
+ autoScroll?: boolean;
23
+ onEndReached?: () => void;
24
+ onLikePress?: (id: string, liked: boolean) => void;
25
+ onEpisodesPress?: (id: string) => void;
26
+ onSharePress?: (id: string) => void;
27
+ onSearchPress?: () => void;
28
+ isFocused?: boolean;
29
+ };
30
+
31
+ export const ReelsSeries: React.FC<ReelsProps> = ({
32
+ data,
33
+ autoScroll,
34
+ onEndReached,
35
+ onLikePress,
36
+ onEpisodesPress,
37
+ onSharePress,
38
+ onSearchPress,
39
+ isFocused = true,
40
+ }) => {
41
+ const [currentVisibleIndex, setCurrentVisibleIndex] = useState<number>(0);
42
+ const listRef = useRef<FlatList<ISeriesEpisode>>(null);
43
+ const keyExtractor = useCallback(
44
+ (item: ISeriesEpisode) => item.episodeId.toString(),
45
+ []
46
+ );
47
+
48
+ const hendlePlayEpisode = useCallback(
49
+ (index: number) => {
50
+ if (index < 0 || index >= (data.episodes?.length || 0)) return;
51
+ listRef.current?.scrollToIndex({ index, animated: true });
52
+ setCurrentVisibleIndex(index);
53
+ },
54
+ [data.episodes]
55
+ );
56
+
57
+ const renderReelList = useCallback(
58
+ ({ item, index }: { item: ISeriesEpisode; index: number }) => {
59
+ return (
60
+ <ReelsSeriesItem
61
+ key={item.episodeId}
62
+ reel={item}
63
+ data={data}
64
+ videoHeight={SCREEN_HEIGHT}
65
+ onLikePress={onLikePress}
66
+ onEpisodesPress={() => onEpisodesPress?.(item.episodeId)}
67
+ onSharePress={() => onSharePress?.(item.episodeId)}
68
+ isVisible={index === currentVisibleIndex && isFocused}
69
+ activeEpisodeIndex={currentVisibleIndex}
70
+ preload={Math.abs(currentVisibleIndex + 3) >= index}
71
+ onEpisodeSelect={hendlePlayEpisode}
72
+ autoScroll={autoScroll}
73
+ />
74
+ );
75
+ },
76
+ [
77
+ data,
78
+ onLikePress,
79
+ currentVisibleIndex,
80
+ isFocused,
81
+ hendlePlayEpisode,
82
+ autoScroll,
83
+ onEpisodesPress,
84
+ onSharePress,
85
+ ]
86
+ );
87
+
88
+ const memoizedRenderReelList = useMemo(
89
+ () => renderReelList,
90
+ [renderReelList]
91
+ );
92
+
93
+ const viewabilityConfig = useRef({
94
+ itemVisiblePercentThreshold: 80,
95
+ }).current;
96
+
97
+ const onViewableItemsChanged = useRef(
98
+ debounce(({ viewableItems }: { viewableItems: Array<ViewToken> }) => {
99
+ if (viewableItems.length > 0) {
100
+ setCurrentVisibleIndex(viewableItems[0]?.index || 0);
101
+ }
102
+ }, 100)
103
+ ).current;
104
+
105
+ const getItemLayout = useCallback(
106
+ (_: any, index: number) => ({
107
+ length: SCREEN_HEIGHT,
108
+ offset: SCREEN_HEIGHT * index,
109
+ index,
110
+ }),
111
+ []
112
+ );
113
+
114
+ return (
115
+ <View style={[styles.container, { backgroundColor: '#000' }]}>
116
+ {onSearchPress && (
117
+ <TouchableOpacity
118
+ style={[
119
+ styles.fixedSearch,
120
+ {
121
+ top: verticalScale(40),
122
+ right: 16,
123
+ },
124
+ ]}
125
+ onPress={onSearchPress}
126
+ >
127
+ <Search color={'#fff'} size={verticalScale(22)} />
128
+ </TouchableOpacity>
129
+ )}
130
+
131
+ <FlatList
132
+ ref={listRef}
133
+ data={data.episodes || []}
134
+ keyExtractor={keyExtractor}
135
+ renderItem={memoizedRenderReelList as any}
136
+ windowSize={2}
137
+ onEndReached={onEndReached}
138
+ pagingEnabled
139
+ viewabilityConfig={viewabilityConfig}
140
+ disableIntervalMomentum={true}
141
+ removeClippedSubviews
142
+ maxToRenderPerBatch={2}
143
+ onViewableItemsChanged={onViewableItemsChanged}
144
+ initialNumToRender={1}
145
+ onEndReachedThreshold={0.1}
146
+ decelerationRate="fast"
147
+ showsVerticalScrollIndicator={false}
148
+ scrollEventThrottle={16}
149
+ snapToInterval={SCREEN_HEIGHT}
150
+ snapToAlignment="start"
151
+ getItemLayout={getItemLayout}
152
+ contentContainerStyle={{ paddingBottom: TAB_BAR_HEIGHT }}
153
+ />
154
+ </View>
155
+ );
156
+ };
157
+
158
+ export default ReelsSeries;
159
+
160
+ const styles = StyleSheet.create({
161
+ container: { flex: 1 },
162
+ fixedSearch: { position: 'absolute', zIndex: 10 },
163
+ });
@@ -0,0 +1,333 @@
1
+ import React, { useState, useEffect, useRef, useCallback, memo } from 'react';
2
+ import { View, Dimensions, StyleSheet } from 'react-native';
3
+ import ReelSeriesOverlay from './ReelSeriesOverlay';
4
+ import ReelSeriesDetailsModal from './ReelSeriesDetailsModal';
5
+ import type { ISeriesEpisode, ISeriesItem } from './types';
6
+ import { Video, type VideoRef } from 'react-native-video';
7
+ import FastImage from 'react-native-fast-image';
8
+ import {
9
+ Gesture,
10
+ GestureDetector,
11
+ GestureHandlerRootView,
12
+ } from 'react-native-gesture-handler';
13
+ import { Pause, Play } from 'lucide-react-native';
14
+ import { moderateScale } from 'react-native-size-matters';
15
+ import LottieView from 'lottie-react-native';
16
+ import DoubleTapAnim from '../../../assets/animations/heart.json';
17
+
18
+ const { width } = Dimensions.get('window');
19
+
20
+ interface IReelItemProps {
21
+ reel: ISeriesEpisode;
22
+ data: ISeriesItem;
23
+ autoScroll?: boolean;
24
+ videoHeight: number;
25
+ onLikePress?: (id: string, liked: boolean) => void;
26
+ onEpisodesPress?: () => void;
27
+ onSharePress?: () => void;
28
+ isVisible: boolean;
29
+ preload: boolean;
30
+ activeEpisodeIndex: number;
31
+ onEpisodeSelect: (index: number) => void;
32
+ }
33
+
34
+ const ReelItem: React.FC<IReelItemProps> = ({
35
+ reel,
36
+ data,
37
+ autoScroll,
38
+ videoHeight,
39
+ onLikePress,
40
+ onSharePress,
41
+ isVisible,
42
+ preload,
43
+ activeEpisodeIndex,
44
+ onEpisodeSelect,
45
+ }) => {
46
+ const videoRef = useRef<VideoRef>(null);
47
+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
48
+ const [isPaused, setIsPaused] = useState<boolean>(false);
49
+ const [paused, setPaused] = useState<string | null>(null);
50
+ const [modalVisible, setModalVisible] = useState(false);
51
+ const [currentTime, setCurrentTime] = useState(0);
52
+ const [duration, setDuration] = useState(0);
53
+ const [videoLoaded, setVideoLoaded] = useState(false);
54
+ const [showLikeAnim, setShowLikeAnim] = useState<boolean>(false);
55
+
56
+ useEffect(() => {
57
+ setIsPaused(!isVisible);
58
+ if (!isVisible) {
59
+ setPaused(null);
60
+ setVideoLoaded(false);
61
+ }
62
+ }, [isVisible]);
63
+
64
+ // Cleanup timeout on unmount
65
+ useEffect(() => {
66
+ return () => {
67
+ if (timeoutRef.current) {
68
+ clearTimeout(timeoutRef.current);
69
+ }
70
+ };
71
+ }, []);
72
+
73
+ const videoUri = reel.videoUrl || '';
74
+ // Handle like
75
+ const handleLikePress = useCallback(() => {
76
+ const newLiked = !data.isLiked;
77
+ data.isLiked = newLiked;
78
+ data.likes += newLiked ? 1 : -1;
79
+ if (newLiked) {
80
+ setShowLikeAnim(true);
81
+ setTimeout(() => setShowLikeAnim(false), 1200);
82
+ }
83
+ onLikePress?.(reel.episodeId, newLiked);
84
+ }, [data, onLikePress, reel.episodeId]);
85
+
86
+ const handleEpisodeSelect = (index: number) => {
87
+ if (data && index >= 0 && index < data.episodes.length) {
88
+ onEpisodeSelect(index);
89
+ setModalVisible(false);
90
+ }
91
+ };
92
+
93
+ const handleVideoLoad = () => {
94
+ setVideoLoaded(true);
95
+ };
96
+
97
+ const handleTogglePlay = useCallback(() => {
98
+ // Use functional updates to ensure we get the current state
99
+ setIsPaused((prevIsPaused) => {
100
+ const newIsPaused = !prevIsPaused;
101
+ const currentState = newIsPaused ? 'paused' : 'play';
102
+
103
+ setPaused(currentState);
104
+
105
+ // Clear any existing timeout
106
+ if (timeoutRef.current) {
107
+ clearTimeout(timeoutRef.current);
108
+ }
109
+
110
+ // Set new timeout
111
+ timeoutRef.current = setTimeout(() => {
112
+ if (currentState === 'play') {
113
+ setPaused(null);
114
+ }
115
+ }, 700);
116
+
117
+ return newIsPaused;
118
+ });
119
+ }, []);
120
+
121
+ const singleTap = Gesture.Tap()
122
+ .maxDuration(300)
123
+ .onStart((event) => {
124
+ // Check if the tap is in the overlay area (right side icons or bottom area)
125
+ const { x, y } = event;
126
+ const screenWidth = width;
127
+ const screenHeight = videoHeight;
128
+
129
+ // Right side icons area (right 80px)
130
+ const rightIconsArea = x > screenWidth - 80;
131
+
132
+ // Bottom area (bottom 150px)
133
+ const bottomArea = y > screenHeight - 150;
134
+
135
+ // If tap is in overlay area, don't trigger play/pause
136
+ if (rightIconsArea || bottomArea) {
137
+ return;
138
+ }
139
+ handleTogglePlay();
140
+ })
141
+ .runOnJS(true);
142
+
143
+ const doubleTap = Gesture.Tap()
144
+ .maxDuration(300)
145
+ .numberOfTaps(2)
146
+ .onStart((event) => {
147
+ // Check if the tap is in the overlay area (right side icons or bottom area)
148
+ const { x, y } = event;
149
+ const screenWidth = width;
150
+ const screenHeight = videoHeight;
151
+
152
+ // Right side icons area (right 80px)
153
+ const rightIconsArea = x > screenWidth - 80;
154
+
155
+ // Bottom area (bottom 150px)
156
+ const bottomArea = y > screenHeight - 150;
157
+
158
+ // If tap is in overlay area, don't trigger like
159
+ if (rightIconsArea || bottomArea) {
160
+ return;
161
+ }
162
+
163
+ handleLikePress();
164
+ })
165
+ .runOnJS(true);
166
+
167
+ const combined = Gesture.Exclusive(doubleTap, singleTap);
168
+
169
+ return (
170
+ <View
171
+ style={[
172
+ styles.container,
173
+ { height: videoHeight, backgroundColor: '#000' },
174
+ ]}
175
+ >
176
+ <GestureHandlerRootView style={{ flex: 1 }}>
177
+ <GestureDetector gesture={combined}>
178
+ <View style={{ flex: 1 }} collapsable={false}>
179
+ {/* Video Player */}
180
+ {!videoLoaded && (
181
+ <FastImage
182
+ source={{
183
+ uri: data.thumbnail,
184
+ priority: FastImage.priority.high,
185
+ }}
186
+ defaultSource={require('../../../assets/img/play.png')}
187
+ resizeMode={FastImage.resizeMode.cover}
188
+ />
189
+ )}
190
+
191
+ {isVisible || preload ? (
192
+ <Video
193
+ poster={data.thumbnail}
194
+ ref={videoRef}
195
+ source={{ uri: videoUri }}
196
+ style={StyleSheet.absoluteFillObject}
197
+ resizeMode="cover"
198
+ posterResizeMode="cover"
199
+ repeat
200
+ paused={isPaused}
201
+ onLoad={(e) => setDuration(e.duration)}
202
+ onProgress={({ currentTime: ct }) => setCurrentTime(ct)}
203
+ ignoreSilentSwitch="ignore"
204
+ playWhenInactive={false}
205
+ playInBackground={false}
206
+ controls={false}
207
+ controlsStyles={{
208
+ hideForward: true,
209
+ hideDuration: true,
210
+ hideFullscreen: true,
211
+ hidePlayPause: true,
212
+ hideNavigationBarOnFullScreenMode: true,
213
+ hideNotificationBarOnFullScreenMode: true,
214
+ hideNext: true,
215
+ hidePosition: true,
216
+ hidePrevious: true,
217
+ hideRewind: true,
218
+ hideSeekBar: true,
219
+ hideSettingButton: true,
220
+ }}
221
+ disableFocus={true}
222
+ shutterColor="transparent"
223
+ onReadyForDisplay={handleVideoLoad}
224
+ onEnd={() => {
225
+ if (autoScroll) {
226
+ onEpisodeSelect(activeEpisodeIndex + 1);
227
+ }
228
+ }}
229
+ />
230
+ ) : null}
231
+
232
+ {showLikeAnim && (
233
+ <View style={styles.lottieContainer}>
234
+ <LottieView
235
+ style={styles.lottie}
236
+ source={DoubleTapAnim}
237
+ autoPlay
238
+ loop={false}
239
+ />
240
+ </View>
241
+ )}
242
+
243
+ {paused !== null && (
244
+ <View
245
+ style={[
246
+ styles.playPauseButtonContainer,
247
+ { height: videoHeight },
248
+ ]}
249
+ >
250
+ <View style={styles.shadow} pointerEvents="none">
251
+ {paused === 'paused' ? (
252
+ <Pause color={'#fff'} size={moderateScale(25)} />
253
+ ) : (
254
+ <Play color={'#fff'} size={moderateScale(25)} />
255
+ )}
256
+ </View>
257
+ </View>
258
+ )}
259
+
260
+ {/* Overlay */}
261
+ <ReelSeriesOverlay
262
+ data={data}
263
+ reel={reel}
264
+ currentTime={currentTime}
265
+ duration={duration}
266
+ onLikePress={handleLikePress}
267
+ onPlayPausePress={() => setIsPaused((prev) => !prev)}
268
+ onEpisodesPress={() => {
269
+ setModalVisible(true);
270
+ }}
271
+ onSharePress={onSharePress}
272
+ activeEpisodeIndex={activeEpisodeIndex}
273
+ />
274
+
275
+ {/* Modal */}
276
+ <ReelSeriesDetailsModal
277
+ visible={modalVisible}
278
+ onClose={() => setModalVisible(false)}
279
+ reel={reel}
280
+ data={data}
281
+ activeEpisodeIndex={activeEpisodeIndex}
282
+ onEpisodeSelect={handleEpisodeSelect}
283
+ />
284
+ </View>
285
+ </GestureDetector>
286
+ </GestureHandlerRootView>
287
+ </View>
288
+ );
289
+ };
290
+
291
+ const areEqual = (prevProps: IReelItemProps, nextProps: IReelItemProps) => {
292
+ return (
293
+ prevProps?.reel?.episodeId === nextProps?.reel?.episodeId &&
294
+ prevProps?.isVisible === nextProps?.isVisible
295
+ );
296
+ };
297
+
298
+ export default memo(ReelItem, areEqual);
299
+
300
+ const styles = StyleSheet.create({
301
+ container: {
302
+ width,
303
+ position: 'relative',
304
+ overflow: 'hidden',
305
+ flex: 1,
306
+ flexGrow: 1,
307
+ },
308
+ playPauseButtonContainer: {
309
+ position: 'absolute',
310
+ top: 0,
311
+ left: 0,
312
+ right: 0,
313
+ bottom: 0,
314
+ justifyContent: 'center',
315
+ alignItems: 'center',
316
+ },
317
+ shadow: {
318
+ backgroundColor: 'rgba(0,0,0,0.5)',
319
+ padding: moderateScale(10),
320
+ borderRadius: moderateScale(50),
321
+ },
322
+ lottieContainer: {
323
+ width: '100%',
324
+ height: '100%',
325
+ position: 'absolute',
326
+ justifyContent: 'center',
327
+ alignItems: 'center',
328
+ },
329
+ lottie: {
330
+ width: '100%',
331
+ height: '100%',
332
+ },
333
+ });
@@ -0,0 +1,27 @@
1
+ export interface ISeriesEpisode {
2
+ videoUrl: string;
3
+ episodeId: string;
4
+ episodeNumber: number;
5
+ duration: string;
6
+ isLocked: boolean;
7
+ }
8
+
9
+ export interface ISeriesItem {
10
+ id: string;
11
+ title: string;
12
+
13
+ thumbnail: string;
14
+ description: string;
15
+ episodes: ISeriesEpisode[];
16
+ likes: number;
17
+ views: number;
18
+ createdAt: string;
19
+ shares: number;
20
+ isLiked: boolean;
21
+ }
22
+
23
+ // For like state
24
+ export interface LikedState {
25
+ liked: boolean;
26
+ count: number;
27
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * @author Naresh Dhamu
3
+ * @lastModified Tue 24 Jun 2025 at 05:02 PM
4
+ */
5
+
6
+ import { ReelsSeries } from './ReelsSeries/ReelsSeries';
7
+ export * from './ReelsSeries/types';
8
+ export { ReelsSeries };
@@ -90,7 +90,7 @@ const SubscriptionSliderOne = ({
90
90
  });
91
91
  }, [plans]);
92
92
  const placeholderData = useMemo(
93
- () => new Array(plans.length || 1).fill({}),
93
+ () => new Array(plans.length || 3).fill({}),
94
94
  [plans]
95
95
  );
96
96
 
@@ -212,7 +212,9 @@ const SubscriptionSliderOne = ({
212
212
  height={CAROUSEL_HEIGHT}
213
213
  data={isLoading ? placeholderData : sortedPlans}
214
214
  renderItem={isLoading ? renderSkeleton : renderPlan}
215
- loop
215
+ loop={
216
+ ((isLoading ? sortedPlans.length : sortedPlans.length) || 0) > 1
217
+ }
216
218
  autoPlay={false}
217
219
  scrollAnimationDuration={500}
218
220
  mode="parallax"
@@ -20,6 +20,7 @@ import AppHeader from '../../Headers/AppHeader';
20
20
  import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
21
21
  import type { AppTheme } from '../../../theme/themes';
22
22
  import { RFValue } from 'react-native-responsive-fontsize';
23
+ import { ScanLine } from 'lucide-react-native';
23
24
 
24
25
  type IUserLocation = {
25
26
  country: string | null;
@@ -57,6 +58,7 @@ type IDeviceSessionsProps = {
57
58
  error?: string;
58
59
  onLogout: ({ session }: { session: ISessions }) => void;
59
60
  onBackPress?: () => void;
61
+ onQrLoginPress?: () => void;
60
62
  style?: StyleProp<ViewStyle>;
61
63
  title?: string;
62
64
  renderLogoutButton?: ({ session }: { session: ISessions }) => React.ReactNode;
@@ -82,6 +84,7 @@ export const DeviceSessions: React.FC<IDeviceSessionsProps> = ({
82
84
  activeSessionId,
83
85
  onLogout,
84
86
  onBackPress = () => {},
87
+ onQrLoginPress,
85
88
  title = 'Manage Devices',
86
89
  style,
87
90
  error,
@@ -309,6 +312,14 @@ export const DeviceSessions: React.FC<IDeviceSessionsProps> = ({
309
312
  <AppHeader
310
313
  title={title}
311
314
  onBackPress={onBackPress}
315
+ onRightPress={onQrLoginPress}
316
+ rightIcon={
317
+ <ScanLine
318
+ size={22}
319
+ strokeWidth={2}
320
+ color={colors.onSurfaceVariant}
321
+ />
322
+ }
312
323
  titleAlign={headerTitleAlign}
313
324
  style={headerStyle}
314
325
  titleStyle={headerTitleStyle}