@zezosoft/zezo-ott-react-native-ui-kit 1.0.6 → 1.0.7

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 (101) hide show
  1. package/lib/module/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.js +69 -45
  2. package/lib/module/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.js.map +1 -1
  3. package/lib/module/components/Content/Card/components/CardPoster.js +5 -0
  4. package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
  5. package/lib/module/components/Content/Content.js +22 -7
  6. package/lib/module/components/Content/Content.js.map +1 -1
  7. package/lib/module/components/ContentView/ContentView.js +99 -83
  8. package/lib/module/components/ContentView/ContentView.js.map +1 -1
  9. package/lib/module/components/ContentView/components/AboutSection.js +15 -1
  10. package/lib/module/components/ContentView/components/AboutSection.js.map +1 -1
  11. package/lib/module/components/ContentView/components/CastCard.js +1 -1
  12. package/lib/module/components/ContentView/components/HeroBanner.js +44 -17
  13. package/lib/module/components/ContentView/components/HeroBanner.js.map +1 -1
  14. package/lib/module/components/ContentView/components/MiniInfo.js +136 -0
  15. package/lib/module/components/ContentView/components/MiniInfo.js.map +1 -0
  16. package/lib/module/components/ContentView/components/Title.js +19 -27
  17. package/lib/module/components/ContentView/components/Title.js.map +1 -1
  18. package/lib/module/components/{Content/Card/components → Fallbacks}/NoContentFallback.js +49 -32
  19. package/lib/module/components/Fallbacks/NoContentFallback.js.map +1 -0
  20. package/lib/module/components/Fallbacks/NotFoundFallback.js +79 -0
  21. package/lib/module/components/Fallbacks/NotFoundFallback.js.map +1 -0
  22. package/lib/module/components/Fallbacks/index.js +5 -0
  23. package/lib/module/components/Fallbacks/index.js.map +1 -0
  24. package/lib/module/components/Input/InputOne.js +9 -3
  25. package/lib/module/components/Input/InputOne.js.map +1 -1
  26. package/lib/module/components/Text/Text.js +31 -10
  27. package/lib/module/components/Text/Text.js.map +1 -1
  28. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js +2 -2
  29. package/lib/module/components/User/ProfileUpdate/ProfileUpdate.js.map +1 -1
  30. package/lib/module/components/View/View.js.map +1 -1
  31. package/lib/module/components/index.js +3 -1
  32. package/lib/module/components/index.js.map +1 -1
  33. package/lib/module/store/themeStore.js +26 -29
  34. package/lib/module/store/themeStore.js.map +1 -1
  35. package/lib/module/theme/ThemeProvider.js.map +1 -1
  36. package/lib/module/theme/hook/useInternalTheme.js +36 -25
  37. package/lib/module/theme/hook/useInternalTheme.js.map +1 -1
  38. package/lib/module/theme/themes.js +14 -2
  39. package/lib/module/theme/themes.js.map +1 -1
  40. package/lib/typescript/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.d.ts +7 -6
  41. package/lib/typescript/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.d.ts.map +1 -1
  42. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts +4 -0
  43. package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
  44. package/lib/typescript/src/components/Content/Content.d.ts +2 -0
  45. package/lib/typescript/src/components/Content/Content.d.ts.map +1 -1
  46. package/lib/typescript/src/components/ContentView/ContentView.d.ts +1 -5
  47. package/lib/typescript/src/components/ContentView/ContentView.d.ts.map +1 -1
  48. package/lib/typescript/src/components/ContentView/components/AboutSection.d.ts +6 -3
  49. package/lib/typescript/src/components/ContentView/components/AboutSection.d.ts.map +1 -1
  50. package/lib/typescript/src/components/ContentView/components/HeroBanner.d.ts.map +1 -1
  51. package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts +22 -0
  52. package/lib/typescript/src/components/ContentView/components/MiniInfo.d.ts.map +1 -0
  53. package/lib/typescript/src/components/Fallbacks/NoContentFallback.d.ts +16 -0
  54. package/lib/typescript/src/components/Fallbacks/NoContentFallback.d.ts.map +1 -0
  55. package/lib/typescript/src/components/Fallbacks/NotFoundFallback.d.ts +19 -0
  56. package/lib/typescript/src/components/Fallbacks/NotFoundFallback.d.ts.map +1 -0
  57. package/lib/typescript/src/components/Fallbacks/index.d.ts +3 -0
  58. package/lib/typescript/src/components/Fallbacks/index.d.ts.map +1 -0
  59. package/lib/typescript/src/components/Input/InputOne.d.ts.map +1 -1
  60. package/lib/typescript/src/components/Text/Text.d.ts +1 -4
  61. package/lib/typescript/src/components/Text/Text.d.ts.map +1 -1
  62. package/lib/typescript/src/components/View/View.d.ts +2 -2
  63. package/lib/typescript/src/components/View/View.d.ts.map +1 -1
  64. package/lib/typescript/src/components/index.d.ts +3 -1
  65. package/lib/typescript/src/components/index.d.ts.map +1 -1
  66. package/lib/typescript/src/store/themeStore.d.ts +19 -1
  67. package/lib/typescript/src/store/themeStore.d.ts.map +1 -1
  68. package/lib/typescript/src/theme/ThemeProvider.d.ts.map +1 -1
  69. package/lib/typescript/src/theme/hook/useInternalTheme.d.ts +4 -0
  70. package/lib/typescript/src/theme/hook/useInternalTheme.d.ts.map +1 -1
  71. package/lib/typescript/src/theme/themes.d.ts +6 -0
  72. package/lib/typescript/src/theme/themes.d.ts.map +1 -1
  73. package/lib/typescript/src/types/content/content-view.types.d.ts +7 -0
  74. package/lib/typescript/src/types/content/content-view.types.d.ts.map +1 -1
  75. package/package.json +1 -1
  76. package/src/components/Auth/SplashScreen/components/SplashVideo/SplashVideo.tsx +88 -72
  77. package/src/components/Content/Card/components/CardPoster.tsx +5 -0
  78. package/src/components/Content/Content.tsx +23 -3
  79. package/src/components/ContentView/ContentView.tsx +110 -86
  80. package/src/components/ContentView/components/AboutSection.tsx +23 -3
  81. package/src/components/ContentView/components/CastCard.tsx +1 -1
  82. package/src/components/ContentView/components/HeroBanner.tsx +45 -17
  83. package/src/components/ContentView/components/MiniInfo.tsx +193 -0
  84. package/src/components/ContentView/components/Title.tsx +17 -26
  85. package/src/components/Fallbacks/NoContentFallback.tsx +172 -0
  86. package/src/components/Fallbacks/NotFoundFallback.tsx +86 -0
  87. package/src/components/Fallbacks/index.ts +2 -0
  88. package/src/components/Input/InputOne.tsx +26 -3
  89. package/src/components/Text/Text.tsx +21 -11
  90. package/src/components/User/ProfileUpdate/ProfileUpdate.tsx +2 -2
  91. package/src/components/View/View.tsx +2 -1
  92. package/src/components/index.ts +3 -1
  93. package/src/store/themeStore.ts +33 -43
  94. package/src/theme/ThemeProvider.tsx +0 -1
  95. package/src/theme/hook/useInternalTheme.ts +46 -24
  96. package/src/theme/themes.ts +20 -0
  97. package/src/types/content/content-view.types.ts +7 -0
  98. package/lib/module/components/Content/Card/components/NoContentFallback.js.map +0 -1
  99. package/lib/typescript/src/components/Content/Card/components/NoContentFallback.d.ts +0 -17
  100. package/lib/typescript/src/components/Content/Card/components/NoContentFallback.d.ts.map +0 -1
  101. package/src/components/Content/Card/components/NoContentFallback.tsx +0 -147
@@ -1,41 +1,53 @@
1
1
  /**
2
2
  * @author Naresh Dhamu
3
- * @lastModified Thu 17 Oct 2025
3
+ * @lastModified Sat 25 Oct 2025
4
4
  */
5
- import React, { useMemo, useCallback, useState } from 'react';
6
- import { View, StyleSheet, Animated } from 'react-native';
7
- import Video from 'react-native-video';
5
+
6
+ import React, {
7
+ useMemo,
8
+ useCallback,
9
+ useRef,
10
+ useState,
11
+ useEffect,
12
+ } from 'react';
13
+ import { StyleSheet, Animated, View as RNView } from 'react-native';
14
+ import Video, {
15
+ type OnLoadData,
16
+ type OnVideoErrorData,
17
+ } from 'react-native-video';
8
18
  import Display from '../../../../../utils/Display';
9
19
  import { useInternalTheme } from '../../../../../theme/hook';
20
+ import { View } from '../../../../View';
21
+ import { Loader } from '../../../../Loader/Loader';
10
22
 
11
23
  interface IProps {
12
- width: number;
13
- height: number;
24
+ width?: number;
25
+ height?: number;
14
26
  source: string;
15
- fullscreen: boolean;
27
+ fullscreen?: boolean;
16
28
  resizeMode?: 'cover' | 'contain' | 'stretch' | 'none';
17
29
  onEnd?: () => void;
18
30
  onLoadStart?: () => void;
19
- onLoaded?: (data: any) => void;
20
- onError?: (error: any) => void;
31
+ onLoaded?: (data: OnLoadData) => void;
32
+ onError?: (error: string) => void;
21
33
  }
22
34
 
23
35
  const SplashVideo: React.FC<IProps> = ({
24
- fullscreen,
25
- height,
36
+ fullscreen = false,
37
+ width = Display.fullWidth,
38
+ height = Display.fullHeight,
26
39
  source,
27
40
  resizeMode = 'cover',
28
- width,
29
41
  onEnd,
30
42
  onLoadStart,
31
43
  onLoaded,
32
44
  onError,
33
45
  }) => {
34
46
  const { theme: applyTheme } = useInternalTheme();
35
- const [loaded, setLoaded] = useState(false);
36
- const fadeAnim = useMemo(() => new Animated.Value(0), []);
47
+ const fadeAnim = useRef(new Animated.Value(0)).current;
48
+ const [isLoaded, setIsLoaded] = useState(false);
37
49
 
38
- // Video style
50
+ /** 🎨 Compute video dimensions */
39
51
  const videoStyle = useMemo(
40
52
  () => ({
41
53
  width: fullscreen ? Display.fullWidth : width,
@@ -44,77 +56,71 @@ const SplashVideo: React.FC<IProps> = ({
44
56
  [fullscreen, width, height]
45
57
  );
46
58
 
47
- // Event handlers
59
+ /** 🌀 Fade-in animation */
60
+ const animateIn = useCallback(() => {
61
+ Animated.timing(fadeAnim, {
62
+ toValue: 1,
63
+ duration: 400,
64
+ useNativeDriver: true,
65
+ }).start();
66
+ }, [fadeAnim]);
67
+
68
+ /** 📦 Resolve video URI */
69
+ const resolveUri = useCallback((src: string): string => {
70
+ if (!src) return '';
71
+ if (/^(https?|file):\/\//.test(src)) return src;
72
+ return `file://${src}`;
73
+ }, []);
74
+
75
+ /** 🔄 Video lifecycle handlers */
48
76
  const handleLoadStart = useCallback(() => {
49
- setLoaded(false);
50
- fadeAnim.setValue(0); // Reset fade animation
77
+ setIsLoaded(false);
78
+ fadeAnim.setValue(0);
51
79
  onLoadStart?.();
52
- }, [onLoadStart, fadeAnim]);
80
+ }, [fadeAnim, onLoadStart]);
53
81
 
54
82
  const handleLoad = useCallback(
55
- (data: any) => {
56
- setLoaded(true);
57
-
58
- // Fade-in animation
59
- Animated.timing(fadeAnim, {
60
- toValue: 1,
61
- duration: 400, // 0.4s smooth fade
62
- useNativeDriver: true,
63
- }).start();
64
-
83
+ (data: OnLoadData) => {
84
+ setIsLoaded(true);
85
+ animateIn();
65
86
  onLoaded?.(data);
66
87
  },
67
- [onLoaded, fadeAnim]
88
+ [animateIn, onLoaded]
68
89
  );
69
90
 
70
91
  const handleError = useCallback(
71
- (e: any) => {
72
- const error =
73
- e?.error?.message ||
74
- e?.message ||
75
- e?.error ||
76
- e ||
92
+ (err: OnVideoErrorData | any) => {
93
+ const errorMsg =
94
+ err?.error?.message ||
95
+ err?.message ||
96
+ JSON.stringify(err) ||
77
97
  'Unknown video error';
78
- console.error('Video playback error:', error);
79
- setLoaded(false);
80
- onError?.(error);
98
+ console.error('🎬 SplashVideo Error:', errorMsg);
99
+ setIsLoaded(false);
100
+ onError?.(errorMsg);
81
101
  },
82
102
  [onError]
83
103
  );
84
104
 
85
- const resolveUri = (src?: string): string => {
86
- if (!src) return '';
87
- if (
88
- src.startsWith('http') ||
89
- src.startsWith('https') ||
90
- src.startsWith('file://')
91
- ) {
92
- return src;
93
- }
94
- return `file://${src}`;
95
- };
105
+ /** 🧹 Cleanup animation */
106
+ useEffect(() => {
107
+ return () => fadeAnim.stopAnimation();
108
+ }, [fadeAnim]);
96
109
 
110
+ /** 🧱 Render */
97
111
  return (
98
- <View
99
- style={[
100
- videoStyle,
101
- styles.wrapper,
102
- { backgroundColor: applyTheme.colors.background },
103
- ]}
104
- >
105
- {/* Black background layer */}
106
- {!loaded && (
107
- <View
108
- style={[
109
- videoStyle,
110
- styles.blackLayer,
111
- { backgroundColor: applyTheme.colors.background },
112
- ]}
113
- />
112
+ <View style={styles.container}>
113
+ {/* Loader shown before video fully loads */}
114
+ {!isLoaded && (
115
+ <RNView style={styles.loaderWrapper}>
116
+ <Loader color={applyTheme.colors.primary} />
117
+ </RNView>
114
118
  )}
115
119
 
116
- {/* Animated video */}
117
- <Animated.View style={[videoStyle, { opacity: fadeAnim }]}>
120
+ {/* Video Layer */}
121
+ <Animated.View
122
+ style={[videoStyle, { opacity: fadeAnim, position: 'absolute' }]}
123
+ >
118
124
  <Video
119
125
  source={{ uri: resolveUri(source) }}
120
126
  style={videoStyle}
@@ -143,6 +149,8 @@ const SplashVideo: React.FC<IProps> = ({
143
149
  playWhenInactive={false}
144
150
  allowsExternalPlayback={false}
145
151
  automaticallyWaitsToMinimizeStalling
152
+ controls={false}
153
+ repeat={false}
146
154
  />
147
155
  </Animated.View>
148
156
  </View>
@@ -150,14 +158,22 @@ const SplashVideo: React.FC<IProps> = ({
150
158
  };
151
159
 
152
160
  const styles = StyleSheet.create({
153
- wrapper: {
154
- overflow: 'hidden',
161
+ container: {
162
+ flex: 1,
163
+ position: 'relative',
164
+ justifyContent: 'center',
165
+ alignItems: 'center',
155
166
  },
156
- blackLayer: {
157
- ...StyleSheet.absoluteFillObject,
158
167
 
168
+ loaderWrapper: {
169
+ ...StyleSheet.absoluteFillObject,
170
+ justifyContent: 'center',
171
+ alignItems: 'center',
159
172
  zIndex: 1,
160
173
  },
174
+ loader: {
175
+ transform: [{ scale: 1.2 }],
176
+ },
161
177
  });
162
178
 
163
179
  export default React.memo(SplashVideo);
@@ -1,3 +1,8 @@
1
+ /**
2
+ * @author Naresh Dhamu
3
+ * @lastModified Sat 25 Oct 2025 at 04:01 PM
4
+ */
5
+
1
6
  import React, { useState, useEffect, useMemo } from 'react';
2
7
  import { View, StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
3
8
  import FastImage, {
@@ -22,9 +22,10 @@ import SectionType from './Sections';
22
22
  import type { IContentData, IGetSectionData, MoreFetchData } from '../../types';
23
23
  import { dummySections } from '../../constants/dummySections';
24
24
  import CategoryCard, { type ICategory } from './Card/Category/Category';
25
- import NoContentFallback from './Card/components/NoContentFallback';
26
25
  import type { IHistoryItem } from './Card/NowWatching/NowWatching';
27
26
  import type { ThemeOverride } from '../../theme/themes';
27
+ import { NoContentFallback, type NoContentFallbackProps } from '../Fallbacks';
28
+ import { useInternalTheme } from '../../theme/hook';
28
29
 
29
30
  export interface ICustomComponentsForContent {
30
31
  type: string;
@@ -75,6 +76,8 @@ export interface IContentProps {
75
76
  moreFetchData?: MoreFetchData<IContentData>;
76
77
  moreFetchDataHistory?: MoreFetchData<IHistoryItem>;
77
78
  isLoading?: IContentLoading;
79
+
80
+ noContentFallbackProps?: NoContentFallbackProps;
78
81
  }
79
82
 
80
83
  const AnimatedFlatList = Animated.createAnimatedComponent(
@@ -85,6 +88,8 @@ interface FooterProps {
85
88
  ErrorComponent?: React.ReactNode;
86
89
  InfiniteScrollIsLoading?: boolean;
87
90
  InfiniteScrollLoaderComponent?: React.ReactNode;
91
+ theme?: ThemeOverride;
92
+ noContentFallbackProps?: NoContentFallbackProps;
88
93
  }
89
94
 
90
95
  const ContentFooter = ({
@@ -92,7 +97,10 @@ const ContentFooter = ({
92
97
  ErrorComponent,
93
98
  InfiniteScrollIsLoading,
94
99
  InfiniteScrollLoaderComponent,
100
+ theme,
101
+ noContentFallbackProps,
95
102
  }: FooterProps) => {
103
+ const { theme: appliedTheme } = useInternalTheme(theme);
96
104
  if (InfiniteScrollIsLoading) {
97
105
  return (
98
106
  InfiniteScrollLoaderComponent ?? (
@@ -101,16 +109,25 @@ const ContentFooter = ({
101
109
  paddingVertical: scale(30),
102
110
  alignItems: 'center',
103
111
  justifyContent: 'center',
112
+ backgroundColor: 'transparent',
104
113
  }}
105
114
  >
106
- <ActivityIndicator size="small" />
115
+ <ActivityIndicator size="large" color={appliedTheme.colors.primary} />
107
116
  </Animated.View>
108
117
  )
109
118
  );
110
119
  }
111
120
 
112
121
  if (isEmpty) {
113
- return ErrorComponent ? <>{ErrorComponent}</> : <NoContentFallback />;
122
+ return ErrorComponent ? (
123
+ <>{ErrorComponent}</>
124
+ ) : (
125
+ <NoContentFallback
126
+ theme={theme}
127
+ {...noContentFallbackProps}
128
+ isLoading={noContentFallbackProps?.isLoading ?? false}
129
+ />
130
+ );
114
131
  }
115
132
 
116
133
  return null;
@@ -131,6 +148,7 @@ export const Content: React.FC<IContentProps> = ({
131
148
  moreFetchData,
132
149
  moreFetchDataHistory,
133
150
  isLoading,
151
+ noContentFallbackProps,
134
152
  }) => {
135
153
  const sectionData = useMemo<IGetSectionData[]>(
136
154
  () => contentData?.sectionData ?? [],
@@ -223,6 +241,8 @@ export const Content: React.FC<IContentProps> = ({
223
241
  InfiniteScrollIsLoading={isLoading?.InfiniteScrollIsLoading}
224
242
  isEmpty={isEmpty}
225
243
  ErrorComponent={ErrorComponent}
244
+ theme={theme}
245
+ noContentFallbackProps={noContentFallbackProps}
226
246
  />
227
247
  }
228
248
  onEndReachedThreshold={0.7}
@@ -2,7 +2,6 @@
2
2
  * @author Naresh Dhamu
3
3
  * @lastModified Tue 01 Jul 2025 at 02:28 PM
4
4
  */
5
-
6
5
  import { ScrollView, StyleSheet } from 'react-native';
7
6
  import { HeroBanner } from './components/HeroBanner';
8
7
  import { GenreTags } from './components/GenreTags';
@@ -14,12 +13,16 @@ import Cards from '../Content/Card';
14
13
  import { scale } from 'react-native-size-matters';
15
14
  import { EpisodeCard } from './components/EpisodeCard';
16
15
  import type { ComponentProps } from '../../types/content/content-view.types';
16
+ import { NotFoundFallback } from '../Fallbacks';
17
+ import { MiniInfo } from './components/MiniInfo';
18
+
17
19
  export const ContentView = ({
18
20
  content,
19
21
  seasons,
20
22
  isLoading = false,
21
23
  seasonsIsLoading = false,
22
24
  theme,
25
+ text,
23
26
  recommendedContent,
24
27
  events,
25
28
  heroBannerProps,
@@ -35,96 +38,117 @@ export const ContentView = ({
35
38
  const seekTime = history?.currentTime || 0;
36
39
  const isComplete = history?.completed || false;
37
40
  const currentEpisode = history?.current_episode;
41
+
42
+ const isNotFound = !isLoading && !content;
43
+
38
44
  return (
39
- <ScrollView
40
- showsVerticalScrollIndicator={false}
41
- keyboardShouldPersistTaps="handled"
42
- contentContainerStyle={styles.scrollContent}
43
- >
44
- <HeroBanner
45
- backgroundImage={content?.thumbnail}
46
- title={content?.name}
47
- theme={theme}
48
- isLoading={isLoading}
49
- content_offering_type={content?.content_offering_type}
50
- onPressPlay={({ is_trailer }) =>
51
- events?.onPlay?.({
52
- id: content._id,
53
- slug: content.slug,
54
- type: content.type,
55
- current_episode: currentEpisode,
56
- mode: 'fullscreen',
57
- is_trailer,
58
- seekTime: isComplete ? 0 : seekTime,
59
- })
60
- }
61
- onBackPress={events?.onBackPress}
62
- {...heroBannerProps}
63
- />
64
- <Title
65
- title={content?.name}
66
- subtitle={content?.u_age}
67
- rating={content?.rating}
68
- theme={appliedTheme}
69
- isLoading={isLoading}
70
- style={titleStyles}
71
- />
72
- <GenreTags
73
- genres={content?.genres}
74
- theme={appliedTheme}
75
- isLoading={isLoading}
76
- style={genreTagsStyles}
77
- />
78
- <AboutSection
79
- theme={appliedTheme}
80
- description={content?.description}
81
- isLoading={isLoading}
82
- style={aboutSectionStyles}
83
- />
84
- <CastCard
85
- theme={appliedTheme}
86
- data={content?.cast || null}
87
- isLoading={isLoading}
88
- onItemPress={() => {}}
89
- style={castStyles}
90
- />
91
- {content?.type === 'series' &&
92
- (seasonsIsLoading || (seasons && seasons.length > 0)) && (
93
- <EpisodeCard
94
- isLoading={seasonsIsLoading}
95
- seasons={seasonsIsLoading ? [] : (seasons ?? [])}
96
- onPress={({ season_id, episode_id, episode_number }) => {
97
- if (!seasonsIsLoading) {
98
- events?.onPlay?.({
99
- id: content._id,
100
- slug: content.slug,
101
- type: content.type,
102
- current_episode: episode_id,
103
- current_season: season_id,
104
- episode_number,
105
- });
106
- }
107
- }}
45
+ <>
46
+ {isNotFound ? (
47
+ <NotFoundFallback
48
+ title={text?.notFound?.title || 'Oops! Content Not Found'}
49
+ subtitle={
50
+ text?.notFound?.subtitle ||
51
+ 'We couldn’t find anything to show here. Please check back later.'
52
+ }
53
+ backButtonText={text?.notFound?.buttonText || 'Go Back'}
54
+ onPressBack={events?.onBackPress}
55
+ theme={theme}
56
+ />
57
+ ) : (
58
+ <ScrollView
59
+ showsVerticalScrollIndicator={false}
60
+ keyboardShouldPersistTaps="handled"
61
+ contentContainerStyle={styles.scrollContent}
62
+ >
63
+ <HeroBanner
64
+ backgroundImage={content?.thumbnail}
65
+ title={content?.name}
108
66
  theme={theme}
109
- mode={episodeCardMode ?? 'horizontal'}
67
+ isLoading={isLoading}
68
+ content_offering_type={content?.content_offering_type}
69
+ onPressPlay={({ is_trailer }) =>
70
+ events?.onPlay?.({
71
+ id: content._id,
72
+ slug: content.slug,
73
+ type: content.type,
74
+ current_episode: currentEpisode,
75
+ mode: 'fullscreen',
76
+ is_trailer,
77
+ seekTime: isComplete ? 0 : seekTime,
78
+ })
79
+ }
80
+ onBackPress={events?.onBackPress}
81
+ {...heroBannerProps}
82
+ />
83
+ <Title
84
+ title={content?.name}
85
+ subtitle={content?.u_age}
86
+ rating={content?.rating}
87
+ theme={appliedTheme}
88
+ isLoading={isLoading}
89
+ style={titleStyles}
110
90
  />
111
- )}
112
91
 
113
- {recommendedContent && recommendedContent?.content && (
114
- <Cards.Styles.Four
115
- section_id={recommendedContent._id}
116
- title={recommendedContent.name}
117
- type={recommendedContent.type}
118
- data={recommendedContent.content}
119
- isLoading={isLoading}
120
- theme={theme}
121
- onPressItem={(item) => events?.onPressRecommendedItem?.({ item })}
122
- onPressMore={events?.onPressRecommendedMore}
123
- moreFetchData={events?.moreFetchDataRecommended}
124
- {...recommendedContentCardStyles}
125
- />
92
+ <GenreTags
93
+ genres={content?.genres}
94
+ theme={appliedTheme}
95
+ isLoading={isLoading}
96
+ style={genreTagsStyles}
97
+ />
98
+ <MiniInfo content={content} theme={theme} isLoading={isLoading} />
99
+ <AboutSection
100
+ theme={appliedTheme}
101
+ description={content?.description}
102
+ release_year={content?.release_year}
103
+ isLoading={isLoading}
104
+ style={aboutSectionStyles}
105
+ />
106
+ <CastCard
107
+ theme={appliedTheme}
108
+ data={content?.cast || null}
109
+ isLoading={isLoading}
110
+ onItemPress={() => {}}
111
+ style={castStyles}
112
+ />
113
+ {content?.type === 'series' &&
114
+ (seasonsIsLoading || (seasons && seasons.length > 0)) && (
115
+ <EpisodeCard
116
+ isLoading={seasonsIsLoading}
117
+ seasons={seasonsIsLoading ? [] : (seasons ?? [])}
118
+ onPress={({ season_id, episode_id, episode_number }) => {
119
+ if (!seasonsIsLoading) {
120
+ events?.onPlay?.({
121
+ id: content._id,
122
+ slug: content.slug,
123
+ type: content.type,
124
+ current_episode: episode_id,
125
+ current_season: season_id,
126
+ episode_number,
127
+ });
128
+ }
129
+ }}
130
+ theme={theme}
131
+ mode={episodeCardMode ?? 'horizontal'}
132
+ />
133
+ )}
134
+
135
+ {recommendedContent && recommendedContent?.content && (
136
+ <Cards.Styles.Four
137
+ section_id={recommendedContent._id}
138
+ title={recommendedContent.name}
139
+ type={recommendedContent.type}
140
+ data={recommendedContent.content}
141
+ isLoading={isLoading}
142
+ theme={theme}
143
+ onPressItem={(item) => events?.onPressRecommendedItem?.({ item })}
144
+ onPressMore={events?.onPressRecommendedMore}
145
+ moreFetchData={events?.moreFetchDataRecommended}
146
+ {...recommendedContentCardStyles}
147
+ />
148
+ )}
149
+ </ScrollView>
126
150
  )}
127
- </ScrollView>
151
+ </>
128
152
  );
129
153
  };
130
154
 
@@ -18,11 +18,13 @@ import SkeletonPlaceholder from 'react-native-skeleton-placeholder';
18
18
  import { scale, verticalScale } from 'react-native-size-matters';
19
19
  import type { ITheme } from '../../../theme/themes';
20
20
  import { RFValue } from 'react-native-responsive-fontsize';
21
+ import type { IContentData } from '../../../types';
21
22
 
22
23
  type Props = {
23
24
  theme: ITheme;
24
- title?: string;
25
- description?: string;
25
+ title?: IContentData['name'];
26
+ description?: IContentData['description'];
27
+ release_year?: IContentData['release_year'];
26
28
  isLoading?: boolean;
27
29
  style?: {
28
30
  container?: StyleProp<ViewStyle>;
@@ -31,12 +33,14 @@ type Props = {
31
33
  scrollExpanded?: StyleProp<ViewStyle>;
32
34
  toggleText?: StyleProp<TextStyle>;
33
35
  skeletonLine?: StyleProp<ViewStyle>;
36
+ releaseYear?: StyleProp<ViewStyle>;
34
37
  };
35
38
  };
36
39
 
37
40
  export const AboutSection = ({
38
41
  theme,
39
42
  title = 'About',
43
+ release_year,
40
44
  description,
41
45
  isLoading = false,
42
46
  style,
@@ -89,6 +93,16 @@ export const AboutSection = ({
89
93
  {title}
90
94
  </Text>
91
95
 
96
+ {/* Release Year */}
97
+ {release_year && (
98
+ <Text
99
+ color={theme.colors.textSecondary}
100
+ style={[styles.releaseYear, style?.releaseYear]}
101
+ >
102
+ Release: <Text color={theme.colors.textPrimary}>{release_year}</Text>
103
+ </Text>
104
+ )}
105
+
92
106
  {!expanded ? (
93
107
  <Text
94
108
  color={theme.colors.textSecondary}
@@ -137,7 +151,7 @@ const styles = StyleSheet.create({
137
151
  marginTop: verticalScale(7),
138
152
  },
139
153
  title: {
140
- fontSize: RFValue(14),
154
+ fontSize: RFValue(13),
141
155
  fontWeight: 'bold',
142
156
  marginBottom: scale(6),
143
157
  },
@@ -149,6 +163,12 @@ const styles = StyleSheet.create({
149
163
  scrollExpanded: {
150
164
  maxHeight: verticalScale(250),
151
165
  },
166
+ releaseYear: {
167
+ fontSize: RFValue(12),
168
+ fontWeight: '500',
169
+ marginBottom: scale(6),
170
+ letterSpacing: 0.3,
171
+ },
152
172
  toggleText: {
153
173
  fontSize: RFValue(9.5),
154
174
  fontWeight: '600',
@@ -202,7 +202,7 @@ const styles = StyleSheet.create({
202
202
  marginVertical: scale(10),
203
203
  },
204
204
  heading: {
205
- fontSize: RFValue(14),
205
+ fontSize: RFValue(13),
206
206
  fontWeight: 'bold',
207
207
  marginBottom: scale(8),
208
208
  paddingHorizontal: scale(12),