@zezosoft/zezo-ott-react-native-ui-kit 1.1.5 → 1.1.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.
- package/lib/module/components/Content/Card/Sliders/Styles/Three.js +5 -4
- package/lib/module/components/Content/Card/Sliders/Styles/Three.js.map +1 -1
- package/lib/module/components/Headers/Four.js +1 -1
- package/lib/module/components/Headers/Three.js +2 -1
- package/lib/module/components/Headers/Three.js.map +1 -1
- package/lib/typescript/src/components/Content/Card/Sliders/Styles/Three.d.ts.map +1 -1
- package/package.json +2 -14
- package/src/Styles/globalStyles.ts +0 -70
- package/src/assets/animations/135037-payment-processing-error.json +0 -1347
- package/src/assets/animations/7227-vui-animation.json +0 -3377
- package/src/assets/animations/Failed.json +0 -2103
- package/src/assets/animations/Pending.json +0 -522
- package/src/assets/animations/Successful.json +0 -2289
- package/src/assets/animations/heart.json +0 -788
- package/src/assets/animations/succesfull-payment.json +0 -2379
- package/src/assets/animations/voice-icon.json +0 -542
- package/src/assets/img/back.png +0 -0
- package/src/assets/img/bottom-panel.png +0 -0
- package/src/assets/img/camera.png +0 -0
- package/src/assets/img/camera2.png +0 -0
- package/src/assets/img/home.png +0 -0
- package/src/assets/img/lock.png +0 -0
- package/src/assets/img/play.png +0 -0
- package/src/assets/img/profile.jpg +0 -0
- package/src/assets/img/qr-code.png +0 -0
- package/src/assets/img/shadow.png +0 -0
- package/src/assets/img/shadow2.png +0 -0
- package/src/assets/img/user.png +0 -0
- package/src/assets/svg/Account.svg +0 -4
- package/src/assets/svg/Favourite.svg +0 -14
- package/src/assets/svg/Upcoming.svg +0 -4
- package/src/assets/svg/content-error.svg +0 -28
- package/src/assets/svg/download.svg +0 -3
- package/src/assets/svg/eye-off.svg +0 -10
- package/src/assets/svg/favorites.svg +0 -3
- package/src/assets/svg/h.svg +0 -4
- package/src/assets/svg/home.svg +0 -5
- package/src/assets/svg/home1.svg +0 -3
- package/src/assets/svg/menu-bar.svg +0 -4
- package/src/assets/svg/my-space.svg +0 -14
- package/src/assets/svg/play-icon-with-bg.svg +0 -5
- package/src/assets/svg/profile.svg +0 -4
- package/src/assets/svg/search.svg +0 -5
- package/src/assets/svg/search1.svg +0 -4
- package/src/assets/svg/server-error.svg +0 -139
- package/src/components/Account/Account.tsx +0 -367
- package/src/components/Account/index.ts +0 -1
- package/src/components/Alert/AlertDialog.tsx +0 -247
- package/src/components/Alert/UAAlert.tsx +0 -170
- package/src/components/Alert/index.ts +0 -2
- package/src/components/Auth/AuthProvider/AuthProvider.tsx +0 -419
- package/src/components/Auth/One/ForgotPassword/ForgotPassword.tsx +0 -324
- package/src/components/Auth/One/Login/LoginWithEmail.tsx +0 -455
- package/src/components/Auth/One/Login/LoginWithPhone.tsx +0 -306
- package/src/components/Auth/One/OTP/OTP.tsx +0 -465
- package/src/components/Auth/One/QrLogin/QrLogin.tsx +0 -602
- package/src/components/Auth/One/QrLogin/components/QrViewArea.tsx +0 -423
- package/src/components/Auth/One/SignUp/SignUp.tsx +0 -479
- package/src/components/Auth/One/SplashScreen/SplashScreen.tsx +0 -249
- package/src/components/Auth/One/SplashScreen/components/SplashImage/SplashImage.tsx +0 -103
- package/src/components/Auth/One/SplashScreen/components/SplashLottie/SplashLottie.tsx +0 -77
- package/src/components/Auth/One/SplashScreen/components/SplashVideo/SplashVideo.tsx +0 -174
- package/src/components/Auth/One/index.ts +0 -24
- package/src/components/Auth/Two/AuthHeader/AuthHeader.tsx +0 -108
- package/src/components/Auth/Two/ForgotPassword/ForgotPassword.tsx +0 -335
- package/src/components/Auth/Two/Login/AuthLoginShell.tsx +0 -173
- package/src/components/Auth/Two/Login/LoginWithEmail.tsx +0 -279
- package/src/components/Auth/Two/Login/LoginWithPhone.tsx +0 -188
- package/src/components/Auth/Two/OTP/OTP.tsx +0 -465
- package/src/components/Auth/Two/QrLogin/QrLogin.tsx +0 -602
- package/src/components/Auth/Two/QrLogin/components/QrViewArea.tsx +0 -423
- package/src/components/Auth/Two/SignUp/SignUp.tsx +0 -472
- package/src/components/Auth/Two/SplashScreen/SplashScreen.tsx +0 -248
- package/src/components/Auth/Two/SplashScreen/components/SplashImage/SplashImage.tsx +0 -92
- package/src/components/Auth/Two/SplashScreen/components/SplashLottie/SplashLottie.tsx +0 -77
- package/src/components/Auth/Two/SplashScreen/components/SplashVideo/SplashVideo.tsx +0 -178
- package/src/components/Auth/Two/index.ts +0 -28
- package/src/components/Auth/index.ts +0 -11
- package/src/components/BackgroundLayout/BackgroundLayout.tsx +0 -174
- package/src/components/BackgroundLayout/BackgroundLayoutOne.tsx +0 -56
- package/src/components/BlogView/BlogView.tsx +0 -276
- package/src/components/BlogView/index.ts +0 -8
- package/src/components/BlurView/BlurView.tsx +0 -199
- package/src/components/BlurView/index.ts +0 -7
- package/src/components/BottomSheet/BottomSheet.tsx +0 -200
- package/src/components/BottomSheet/BottomSheetOne.tsx +0 -220
- package/src/components/BottomSheet/index.ts +0 -4
- package/src/components/Button/BackBtn.tsx +0 -168
- package/src/components/Button/MenuBtn.tsx +0 -229
- package/src/components/Button/PrimaryBtn.tsx +0 -134
- package/src/components/Button/SecondaryBtn.tsx +0 -132
- package/src/components/Button/TextButton.tsx +0 -145
- package/src/components/Button/index.ts +0 -18
- package/src/components/Content/Card/Category/Category.tsx +0 -436
- package/src/components/Content/Card/Category/CategroyTwo.tsx +0 -429
- package/src/components/Content/Card/NowWatching/NowWatching.tsx +0 -624
- package/src/components/Content/Card/Sliders/Styles/One.tsx +0 -490
- package/src/components/Content/Card/Sliders/Styles/Three.tsx +0 -935
- package/src/components/Content/Card/Sliders/Styles/Two.tsx +0 -391
- package/src/components/Content/Card/Sliders/index.ts +0 -17
- package/src/components/Content/Card/Styles/Five.tsx +0 -385
- package/src/components/Content/Card/Styles/Four.tsx +0 -379
- package/src/components/Content/Card/Styles/One.tsx +0 -386
- package/src/components/Content/Card/Styles/RotateInOut.tsx +0 -413
- package/src/components/Content/Card/Styles/Six.tsx +0 -392
- package/src/components/Content/Card/Styles/Three.tsx +0 -314
- package/src/components/Content/Card/Styles/TopTen.tsx +0 -412
- package/src/components/Content/Card/Styles/Two.tsx +0 -416
- package/src/components/Content/Card/components/AdsPoster.tsx +0 -202
- package/src/components/Content/Card/components/CardPoster.tsx +0 -377
- package/src/components/Content/Card/components/NavigateToMore.tsx +0 -97
- package/src/components/Content/Card/components/RentOrBuyIcon.tsx +0 -129
- package/src/components/Content/Card/components/ShowAllButton.tsx +0 -92
- package/src/components/Content/Card/components/ThumbnailCard.tsx +0 -234
- package/src/components/Content/Card/components/index.ts +0 -1
- package/src/components/Content/Card/index.ts +0 -30
- package/src/components/Content/Content.tsx +0 -315
- package/src/components/Content/Sections.tsx +0 -238
- package/src/components/Content/types.ts +0 -176
- package/src/components/ContentView/MoreContentList.tsx +0 -327
- package/src/components/ContentView/One/ContentViewOne.tsx +0 -243
- package/src/components/ContentView/One/components/AboutSection.tsx +0 -216
- package/src/components/ContentView/One/components/CastCard.tsx +0 -265
- package/src/components/ContentView/One/components/EpisodeCard.tsx +0 -535
- package/src/components/ContentView/One/components/GenreTags.tsx +0 -132
- package/src/components/ContentView/One/components/HeroBanner.tsx +0 -357
- package/src/components/ContentView/One/components/MiniInfo.tsx +0 -356
- package/src/components/ContentView/One/components/PlayButton.tsx +0 -56
- package/src/components/ContentView/One/components/Title.tsx +0 -149
- package/src/components/ContentView/One/components/TrailerButton.tsx +0 -76
- package/src/components/ContentView/Two/ContentViewTwo.tsx +0 -343
- package/src/components/ContentView/Two/components/AboutSection.tsx +0 -216
- package/src/components/ContentView/Two/components/Details.tsx +0 -193
- package/src/components/ContentView/Two/components/EpisodeCard.tsx +0 -602
- package/src/components/ContentView/Two/components/GenreTags.tsx +0 -123
- package/src/components/ContentView/Two/components/HeroBanner.tsx +0 -402
- package/src/components/ContentView/Two/components/LikeShareActions.tsx +0 -125
- package/src/components/ContentView/Two/components/MoreLikeThisContentList .tsx +0 -305
- package/src/components/ContentView/Two/components/PlayOrTrailer.tsx +0 -133
- package/src/components/ContentView/Two/components/SectionTabs.tsx +0 -177
- package/src/components/ContentView/Two/components/Title.tsx +0 -226
- package/src/components/ContentView/Two/components/index.ts +0 -15
- package/src/components/ContentView/index.ts +0 -13
- package/src/components/Fallbacks/NoContentFallback.tsx +0 -176
- package/src/components/Fallbacks/NotFoundFallback.tsx +0 -94
- package/src/components/Fallbacks/index.ts +0 -2
- package/src/components/Headers/AppHeader.tsx +0 -150
- package/src/components/Headers/Four.tsx +0 -83
- package/src/components/Headers/One.tsx +0 -115
- package/src/components/Headers/Three.tsx +0 -135
- package/src/components/Headers/Two.tsx +0 -100
- package/src/components/Headers/index.ts +0 -18
- package/src/components/Input/Input.ts +0 -20
- package/src/components/Input/InputOne.tsx +0 -259
- package/src/components/Input/InputThree.tsx +0 -212
- package/src/components/Input/InputTwo.tsx +0 -212
- package/src/components/Input/PhoneNumberInput.tsx +0 -431
- package/src/components/Input/PhoneNumberInputTwo.tsx +0 -418
- package/src/components/Keyboard/HideKeyboard.tsx +0 -88
- package/src/components/Loader/Loader.tsx +0 -44
- package/src/components/Logo/Logo.tsx +0 -145
- package/src/components/NewRelease/NewReleaseSheet.tsx +0 -250
- package/src/components/NewRelease/index.ts +0 -1
- package/src/components/Reels/ReelsSeries/MediaControls/BottomControls.tsx +0 -221
- package/src/components/Reels/ReelsSeries/MediaControls/MediaControlsProvider.tsx +0 -314
- package/src/components/Reels/ReelsSeries/MediaControls/MiddleControls.tsx +0 -196
- package/src/components/Reels/ReelsSeries/MediaControls/RightControls.tsx +0 -95
- package/src/components/Reels/ReelsSeries/MediaControls/TopControls.tsx +0 -163
- package/src/components/Reels/ReelsSeries/Model/DetailsModal.tsx +0 -210
- package/src/components/Reels/ReelsSeries/Model/SettingModal.tsx +0 -146
- package/src/components/Reels/ReelsSeries/Model/UnlockModal.tsx +0 -154
- package/src/components/Reels/ReelsSeries/ReelsSeries.tsx +0 -264
- package/src/components/Reels/ReelsSeries/ReelsSeriesItem.tsx +0 -494
- package/src/components/Reels/ReelsSeries/components/AnimatedThreeLines.tsx +0 -184
- package/src/components/Reels/ReelsSeries/components/Episodes.tsx +0 -154
- package/src/components/Reels/ReelsSeries/components/GradientOverlay.tsx +0 -41
- package/src/components/Reels/ReelsSeries/components/Like.tsx +0 -40
- package/src/components/Reels/ReelsSeries/components/RotatingLoader.tsx +0 -79
- package/src/components/Reels/ReelsSeries/components/Synopsis.tsx +0 -332
- package/src/components/Reels/ReelsSeries/components/VideoControls/QualityControl.tsx +0 -187
- package/src/components/Reels/ReelsSeries/components/VideoControls/SpeedControl.tsx +0 -80
- package/src/components/Reels/ReelsSeries/components/VideoControls/index.ts +0 -2
- package/src/components/Reels/ReelsSeries/types.ts +0 -54
- package/src/components/Reels/ReelsSeries/useReelsWatchProgress.ts +0 -85
- package/src/components/Reels/ReelsSeries/utils/quality.ts +0 -48
- package/src/components/Reels/index.ts +0 -9
- package/src/components/Reels/utils/Controls/gestureUtils.ts +0 -42
- package/src/components/Reels/utils/Controls/index.ts +0 -4
- package/src/components/Reels/utils/Controls/overlayUtils.ts +0 -35
- package/src/components/Reels/utils/Controls/videoControlsConstants.ts +0 -25
- package/src/components/Reels/utils/Controls/videoRef.ts +0 -4
- package/src/components/Reels/utils/index.ts +0 -1
- package/src/components/Reels/utils/timeoutUtils.ts +0 -29
- package/src/components/Search/One.tsx +0 -256
- package/src/components/Search/components/RecentSearchesSection.tsx +0 -181
- package/src/components/Search/components/SearchCard.tsx +0 -275
- package/src/components/Search/index.ts +0 -16
- package/src/components/Settings/AppSettings.tsx +0 -428
- package/src/components/Settings/index.ts +0 -1
- package/src/components/Subscription/SubOne.tsx +0 -874
- package/src/components/Subscription/index.ts +0 -12
- package/src/components/TabBar/One.tsx +0 -148
- package/src/components/TabBar/Three.tsx +0 -169
- package/src/components/TabBar/Two.tsx +0 -189
- package/src/components/TabBar/index.ts +0 -20
- package/src/components/Text/Text.tsx +0 -85
- package/src/components/Text/index.ts +0 -5
- package/src/components/User/DeviceSessions/DeviceSessions.tsx +0 -468
- package/src/components/User/ProfileUpdate/ProfileUpdate.tsx +0 -278
- package/src/components/User/PurchaseHistory/PurchaseHistory.tsx +0 -494
- package/src/components/User/WatchHistory/WatchHistory.tsx +0 -227
- package/src/components/User/WatchLater/WatchLater.tsx +0 -397
- package/src/components/User/components/UserAvatar.tsx +0 -120
- package/src/components/User/components/UserSection.tsx +0 -228
- package/src/components/User/index.ts +0 -18
- package/src/components/View/View.tsx +0 -37
- package/src/components/View/index.ts +0 -5
- package/src/components/common/AppStatusBar.tsx +0 -57
- package/src/components/index.ts +0 -29
- package/src/components/layout/SafeAreaWrapper.tsx +0 -45
- package/src/components/layout/index.ts +0 -1
- package/src/constants/dummySections.ts +0 -98
- package/src/hooks/Images/index.ts +0 -2
- package/src/hooks/Images/useImageLoader.ts +0 -206
- package/src/hooks/Images/useImageValidation.ts +0 -36
- package/src/hooks/index.ts +0 -17
- package/src/hooks/useAdTracking.ts +0 -349
- package/src/hooks/useCards.ts +0 -228
- package/src/hooks/useDebounce.ts +0 -35
- package/src/hooks/useKeyboard.ts +0 -43
- package/src/hooks/useNavigationMode.ts +0 -46
- package/src/hooks/usePaginatedSection.ts +0 -101
- package/src/hooks/usePrevious.ts +0 -28
- package/src/hooks/useSafeCallback.ts +0 -43
- package/src/hooks/useSkeletonItems.ts +0 -30
- package/src/hooks/useSplashCache.ts +0 -186
- package/src/hooks/useThemeColors.ts +0 -51
- package/src/index.tsx +0 -8
- package/src/store/RecentSearchesStore.ts +0 -78
- package/src/store/splashStore.ts +0 -91
- package/src/store/themeStore.ts +0 -43
- package/src/theme/ThemeProvider.tsx +0 -112
- package/src/theme/hook/index.ts +0 -1
- package/src/theme/hook/useInternalTheme.ts +0 -98
- package/src/theme/index.ts +0 -7
- package/src/theme/themes.ts +0 -336
- package/src/theme/utils/validateColor.ts +0 -127
- package/src/types/content/content-view.types.ts +0 -206
- package/src/types/hook/index.ts +0 -5
- package/src/types/hook/usePaginatedSetion.ts +0 -19
- package/src/types/index.ts +0 -7
- package/src/types/sections/index.ts +0 -84
- package/src/utils/Display.ts +0 -14
- package/src/utils/Formater.ts +0 -14
- package/src/utils/PlatformSelector.ts +0 -29
- package/src/utils/SizeMatters.ts +0 -7
- package/src/utils/Spacing.ts +0 -27
- package/src/utils/colorUtils.ts +0 -70
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
import React, { useState, useEffect, useRef } from 'react';
|
|
2
|
-
import {
|
|
3
|
-
View,
|
|
4
|
-
Text,
|
|
5
|
-
TouchableOpacity,
|
|
6
|
-
StyleSheet,
|
|
7
|
-
ActivityIndicator,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
import { moderateScale, verticalScale } from 'react-native-size-matters';
|
|
10
|
-
import { RFValue } from 'react-native-responsive-fontsize';
|
|
11
|
-
import type { ITheme } from '../../../../../theme';
|
|
12
|
-
import { DEFAULT_QUALITIES, getVideoQualities } from '../../utils/quality';
|
|
13
|
-
|
|
14
|
-
interface QualityControlProps {
|
|
15
|
-
activeQuality: string;
|
|
16
|
-
theme: ITheme;
|
|
17
|
-
onQualityChange: (quality: string) => void;
|
|
18
|
-
videoUrl?: string;
|
|
19
|
-
/**
|
|
20
|
-
* Optional externally-controlled qualities list.
|
|
21
|
-
* When provided, QualityControl will not perform internal fetching
|
|
22
|
-
* and will instead render this list.
|
|
23
|
-
*/
|
|
24
|
-
qualities?: string[];
|
|
25
|
-
/**
|
|
26
|
-
* Optional externally-controlled loading state.
|
|
27
|
-
* Only used when `qualities` is provided.
|
|
28
|
-
*/
|
|
29
|
-
loading?: boolean;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const QualityControl: React.FC<QualityControlProps> = ({
|
|
33
|
-
activeQuality,
|
|
34
|
-
theme,
|
|
35
|
-
onQualityChange,
|
|
36
|
-
videoUrl,
|
|
37
|
-
qualities: externalQualities,
|
|
38
|
-
loading: externalLoading,
|
|
39
|
-
}) => {
|
|
40
|
-
const isControlled = typeof externalQualities !== 'undefined';
|
|
41
|
-
const [qualities, setQualities] = useState<string[]>(
|
|
42
|
-
externalQualities ?? DEFAULT_QUALITIES
|
|
43
|
-
);
|
|
44
|
-
const [loading, setLoading] = useState(false);
|
|
45
|
-
const isMounted = useRef(true);
|
|
46
|
-
|
|
47
|
-
useEffect(() => {
|
|
48
|
-
isMounted.current = true;
|
|
49
|
-
return () => {
|
|
50
|
-
isMounted.current = false;
|
|
51
|
-
};
|
|
52
|
-
}, []);
|
|
53
|
-
|
|
54
|
-
// Keep local state in sync when controlled externally
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
if (isControlled) {
|
|
57
|
-
setQualities(externalQualities ?? DEFAULT_QUALITIES);
|
|
58
|
-
}
|
|
59
|
-
}, [externalQualities, isControlled]);
|
|
60
|
-
|
|
61
|
-
// Uncontrolled mode – fetch qualities internally based on videoUrl
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
if (isControlled) return;
|
|
64
|
-
|
|
65
|
-
const fetchQualities = async () => {
|
|
66
|
-
if (!videoUrl || !videoUrl.includes('.m3u8')) {
|
|
67
|
-
if (isMounted.current) setQualities(DEFAULT_QUALITIES);
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
setLoading(true);
|
|
72
|
-
|
|
73
|
-
try {
|
|
74
|
-
const qualityOptions = await getVideoQualities(videoUrl);
|
|
75
|
-
if (!isMounted.current) return;
|
|
76
|
-
|
|
77
|
-
if (qualityOptions.length > 0) {
|
|
78
|
-
const qualityStrings = [
|
|
79
|
-
'Auto',
|
|
80
|
-
...qualityOptions
|
|
81
|
-
.map((q) => q.quality)
|
|
82
|
-
.filter((v, i, self) => self.indexOf(v) === i)
|
|
83
|
-
.sort((a, b) => parseInt(b, 10) - parseInt(a, 10)),
|
|
84
|
-
];
|
|
85
|
-
setQualities(qualityStrings);
|
|
86
|
-
} else {
|
|
87
|
-
setQualities(DEFAULT_QUALITIES);
|
|
88
|
-
}
|
|
89
|
-
} catch (err) {
|
|
90
|
-
console.error('Failed to fetch qualities:', err);
|
|
91
|
-
if (isMounted.current) setQualities(DEFAULT_QUALITIES);
|
|
92
|
-
} finally {
|
|
93
|
-
if (isMounted.current) setLoading(false);
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
|
|
97
|
-
fetchQualities();
|
|
98
|
-
}, [videoUrl, isControlled]);
|
|
99
|
-
|
|
100
|
-
const isLoading = isControlled ? Boolean(externalLoading) : loading;
|
|
101
|
-
const renderedQualities =
|
|
102
|
-
qualities && qualities.length > 0 ? qualities : DEFAULT_QUALITIES;
|
|
103
|
-
|
|
104
|
-
if (!isControlled && isLoading) {
|
|
105
|
-
return (
|
|
106
|
-
<View style={styles.loadingContainer}>
|
|
107
|
-
<ActivityIndicator size="small" color={theme.colors.button} />
|
|
108
|
-
<Text
|
|
109
|
-
style={[styles.loadingText, { color: theme.colors.textSecondary }]}
|
|
110
|
-
>
|
|
111
|
-
Loading qualities...
|
|
112
|
-
</Text>
|
|
113
|
-
</View>
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
return (
|
|
118
|
-
<View style={styles.container}>
|
|
119
|
-
{renderedQualities.map((quality, index) => {
|
|
120
|
-
const isSelected = activeQuality === quality;
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<TouchableOpacity
|
|
124
|
-
key={index.toString()}
|
|
125
|
-
activeOpacity={0.8}
|
|
126
|
-
style={[
|
|
127
|
-
styles.optionButton,
|
|
128
|
-
{
|
|
129
|
-
backgroundColor: isSelected
|
|
130
|
-
? theme.colors.button
|
|
131
|
-
: theme.colors.surfaceDisabled,
|
|
132
|
-
},
|
|
133
|
-
]}
|
|
134
|
-
onPress={() => onQualityChange(quality)}
|
|
135
|
-
>
|
|
136
|
-
<Text
|
|
137
|
-
style={[
|
|
138
|
-
styles.optionText,
|
|
139
|
-
{
|
|
140
|
-
color: isSelected
|
|
141
|
-
? theme.colors.buttonText
|
|
142
|
-
: theme.colors.textPrimary,
|
|
143
|
-
fontWeight: isSelected ? '700' : '400',
|
|
144
|
-
},
|
|
145
|
-
]}
|
|
146
|
-
>
|
|
147
|
-
{quality}
|
|
148
|
-
</Text>
|
|
149
|
-
</TouchableOpacity>
|
|
150
|
-
);
|
|
151
|
-
})}
|
|
152
|
-
</View>
|
|
153
|
-
);
|
|
154
|
-
};
|
|
155
|
-
|
|
156
|
-
export default React.memo(QualityControl);
|
|
157
|
-
|
|
158
|
-
const styles = StyleSheet.create({
|
|
159
|
-
container: {
|
|
160
|
-
flexDirection: 'row',
|
|
161
|
-
flexWrap: 'wrap',
|
|
162
|
-
justifyContent: 'center',
|
|
163
|
-
gap: moderateScale(10),
|
|
164
|
-
},
|
|
165
|
-
optionButton: {
|
|
166
|
-
width: '30%',
|
|
167
|
-
paddingVertical: verticalScale(12),
|
|
168
|
-
paddingHorizontal: moderateScale(16),
|
|
169
|
-
borderRadius: moderateScale(8),
|
|
170
|
-
alignItems: 'center',
|
|
171
|
-
justifyContent: 'center',
|
|
172
|
-
marginBottom: verticalScale(12),
|
|
173
|
-
},
|
|
174
|
-
optionText: {
|
|
175
|
-
fontSize: RFValue(14),
|
|
176
|
-
},
|
|
177
|
-
loadingContainer: {
|
|
178
|
-
flex: 1,
|
|
179
|
-
justifyContent: 'center',
|
|
180
|
-
alignItems: 'center',
|
|
181
|
-
paddingVertical: verticalScale(40),
|
|
182
|
-
},
|
|
183
|
-
loadingText: {
|
|
184
|
-
marginTop: verticalScale(12),
|
|
185
|
-
fontSize: RFValue(12),
|
|
186
|
-
},
|
|
187
|
-
});
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
3
|
-
import { moderateScale, verticalScale } from 'react-native-size-matters';
|
|
4
|
-
import { RFValue } from 'react-native-responsive-fontsize';
|
|
5
|
-
import type { ITheme } from '../../../../../theme';
|
|
6
|
-
|
|
7
|
-
interface SpeedControlProps {
|
|
8
|
-
activeSpeed: number;
|
|
9
|
-
theme: ITheme;
|
|
10
|
-
onSpeedChange: (speed: number) => void;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const SPEED_OPTIONS = [0.5, 0.75, 1.0, 1.25, 1.5, 2.0];
|
|
14
|
-
|
|
15
|
-
const SpeedControl: React.FC<SpeedControlProps> = ({
|
|
16
|
-
activeSpeed,
|
|
17
|
-
theme,
|
|
18
|
-
onSpeedChange,
|
|
19
|
-
}) => {
|
|
20
|
-
return (
|
|
21
|
-
<View style={styles.container}>
|
|
22
|
-
{SPEED_OPTIONS.map((speed, index) => {
|
|
23
|
-
const isSelected = activeSpeed === speed;
|
|
24
|
-
|
|
25
|
-
return (
|
|
26
|
-
<TouchableOpacity
|
|
27
|
-
key={index.toString()}
|
|
28
|
-
activeOpacity={0.8}
|
|
29
|
-
style={[
|
|
30
|
-
styles.optionButton,
|
|
31
|
-
{
|
|
32
|
-
backgroundColor: isSelected
|
|
33
|
-
? theme.colors.button
|
|
34
|
-
: theme.colors.surfaceDisabled,
|
|
35
|
-
},
|
|
36
|
-
]}
|
|
37
|
-
onPress={() => onSpeedChange(speed)}
|
|
38
|
-
>
|
|
39
|
-
<Text
|
|
40
|
-
style={[
|
|
41
|
-
styles.optionText,
|
|
42
|
-
{
|
|
43
|
-
color: isSelected
|
|
44
|
-
? theme.colors.buttonText
|
|
45
|
-
: theme.colors.textPrimary,
|
|
46
|
-
fontWeight: isSelected ? '700' : '400',
|
|
47
|
-
},
|
|
48
|
-
]}
|
|
49
|
-
>
|
|
50
|
-
{speed}x
|
|
51
|
-
</Text>
|
|
52
|
-
</TouchableOpacity>
|
|
53
|
-
);
|
|
54
|
-
})}
|
|
55
|
-
</View>
|
|
56
|
-
);
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export default React.memo(SpeedControl);
|
|
60
|
-
|
|
61
|
-
const styles = StyleSheet.create({
|
|
62
|
-
container: {
|
|
63
|
-
flexDirection: 'row',
|
|
64
|
-
flexWrap: 'wrap',
|
|
65
|
-
justifyContent: 'space-between',
|
|
66
|
-
marginHorizontal: moderateScale(4), // instead of gap
|
|
67
|
-
},
|
|
68
|
-
optionButton: {
|
|
69
|
-
width: '30%',
|
|
70
|
-
paddingVertical: verticalScale(12),
|
|
71
|
-
paddingHorizontal: moderateScale(16),
|
|
72
|
-
borderRadius: moderateScale(8),
|
|
73
|
-
alignItems: 'center',
|
|
74
|
-
justifyContent: 'center',
|
|
75
|
-
marginBottom: verticalScale(12), // spacing instead of gap
|
|
76
|
-
},
|
|
77
|
-
optionText: {
|
|
78
|
-
fontSize: RFValue(14),
|
|
79
|
-
},
|
|
80
|
-
});
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export interface ILikeMoreData {
|
|
2
|
-
id: string;
|
|
3
|
-
name: string;
|
|
4
|
-
thumbnail: string;
|
|
5
|
-
}
|
|
6
|
-
export interface ISeriesEpisode {
|
|
7
|
-
videoUrl: string;
|
|
8
|
-
episodeId: string;
|
|
9
|
-
episodeNumber: number;
|
|
10
|
-
duration: string;
|
|
11
|
-
isLocked: boolean;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface ISeriesItem {
|
|
15
|
-
id: string;
|
|
16
|
-
title: string;
|
|
17
|
-
thumbnail: string;
|
|
18
|
-
description: string;
|
|
19
|
-
episodes: ISeriesEpisode[];
|
|
20
|
-
likes: number;
|
|
21
|
-
views: number;
|
|
22
|
-
createdAt: string;
|
|
23
|
-
shares: number;
|
|
24
|
-
isLiked: boolean;
|
|
25
|
-
likeMoreData?: ILikeMoreData[];
|
|
26
|
-
}
|
|
27
|
-
export interface IReelsData {
|
|
28
|
-
data: ISeriesItem[];
|
|
29
|
-
}
|
|
30
|
-
// For like state
|
|
31
|
-
export interface LikedState {
|
|
32
|
-
liked: boolean;
|
|
33
|
-
count: number;
|
|
34
|
-
}
|
|
35
|
-
export interface ModalState {
|
|
36
|
-
isVisible: boolean;
|
|
37
|
-
type: 'none' | 'details' | 'settings';
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export interface IReelsWatchProgress {
|
|
41
|
-
series: ISeriesItem;
|
|
42
|
-
episode: ISeriesEpisode;
|
|
43
|
-
currentTime: number;
|
|
44
|
-
duration: number;
|
|
45
|
-
/**
|
|
46
|
-
* Whether the current episode has been watched till (almost) the end.
|
|
47
|
-
*/
|
|
48
|
-
isVideoCompleted: boolean;
|
|
49
|
-
/**
|
|
50
|
-
* Total time (in seconds) this episode has been watched.
|
|
51
|
-
* For short reels this generally matches `currentTime`.
|
|
52
|
-
*/
|
|
53
|
-
totalWatchTime: number;
|
|
54
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import type { IReelsWatchProgress } from './types';
|
|
3
|
-
|
|
4
|
-
type UseReelsWatchProgressParams = {
|
|
5
|
-
/**
|
|
6
|
-
* Whether the parent screen is currently focused/visible.
|
|
7
|
-
* When this becomes false, the last watch progress will be flushed once.
|
|
8
|
-
*/
|
|
9
|
-
isFocused: boolean;
|
|
10
|
-
/**
|
|
11
|
-
* Callback invoked whenever an episode's watch progress should be
|
|
12
|
-
* "finalized" – e.g. when the user switches episodes, leaves the screen
|
|
13
|
-
* or the component unmounts.
|
|
14
|
-
*/
|
|
15
|
-
onFlush: (progress: IReelsWatchProgress) => void;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
type UseReelsWatchProgressResult = {
|
|
19
|
-
/**
|
|
20
|
-
* Pass this directly to `ReelsSeries` / `ReelsSeriesItem` as
|
|
21
|
-
* the `onWatchProgress` handler.
|
|
22
|
-
*/
|
|
23
|
-
handleWatchProgress: (progress: IReelsWatchProgress) => void;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Reusable hook that tracks the last watched episode progress and ensures
|
|
28
|
-
* it is flushed exactly once when:
|
|
29
|
-
* - The user switches to a different episode
|
|
30
|
-
* - The parent screen loses focus
|
|
31
|
-
* - The parent component unmounts
|
|
32
|
-
*
|
|
33
|
-
* This hook is intentionally UI-kit only and delegates side‑effects
|
|
34
|
-
* (API calls, analytics, etc.) to the provided `onFlush` callback.
|
|
35
|
-
*/
|
|
36
|
-
export const useReelsWatchProgress = ({
|
|
37
|
-
isFocused,
|
|
38
|
-
onFlush,
|
|
39
|
-
}: UseReelsWatchProgressParams): UseReelsWatchProgressResult => {
|
|
40
|
-
const lastProgressRef = React.useRef<IReelsWatchProgress | null>(null);
|
|
41
|
-
const flushProgressRef = React.useRef(onFlush);
|
|
42
|
-
|
|
43
|
-
// Always keep the latest flush callback
|
|
44
|
-
React.useEffect(() => {
|
|
45
|
-
flushProgressRef.current = onFlush;
|
|
46
|
-
}, [onFlush]);
|
|
47
|
-
|
|
48
|
-
const handleWatchProgress = React.useCallback(
|
|
49
|
-
(progress: IReelsWatchProgress) => {
|
|
50
|
-
const previous = lastProgressRef.current;
|
|
51
|
-
|
|
52
|
-
// If user changed episode, flush previous episode's progress once
|
|
53
|
-
if (
|
|
54
|
-
previous &&
|
|
55
|
-
previous.episode.episodeId !== progress.episode.episodeId
|
|
56
|
-
) {
|
|
57
|
-
flushProgressRef.current(previous);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Always store the latest progress for the current episode
|
|
61
|
-
lastProgressRef.current = progress;
|
|
62
|
-
},
|
|
63
|
-
[]
|
|
64
|
-
);
|
|
65
|
-
|
|
66
|
-
// When screen loses focus (user navigates away), flush last progress once
|
|
67
|
-
React.useEffect(() => {
|
|
68
|
-
if (!isFocused && lastProgressRef.current) {
|
|
69
|
-
flushProgressRef.current(lastProgressRef.current);
|
|
70
|
-
lastProgressRef.current = null;
|
|
71
|
-
}
|
|
72
|
-
}, [isFocused]);
|
|
73
|
-
|
|
74
|
-
// On unmount, flush any remaining progress
|
|
75
|
-
React.useEffect(() => {
|
|
76
|
-
return () => {
|
|
77
|
-
if (lastProgressRef.current) {
|
|
78
|
-
flushProgressRef.current(lastProgressRef.current);
|
|
79
|
-
lastProgressRef.current = null;
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
}, []);
|
|
83
|
-
|
|
84
|
-
return { handleWatchProgress };
|
|
85
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
export interface QualityOption {
|
|
2
|
-
quality: string;
|
|
3
|
-
url: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export const DEFAULT_QUALITIES = ['Auto', '1080p', '720p', '480p', '360p'];
|
|
7
|
-
|
|
8
|
-
// Simple in-memory cache to avoid fetching the same playlist multiple times
|
|
9
|
-
const qualitiesCache: Record<string, QualityOption[]> = {};
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Fetches available video qualities from m3u8 playlist.
|
|
13
|
-
*/
|
|
14
|
-
export const getVideoQualities = async (
|
|
15
|
-
m3u8Url: string
|
|
16
|
-
): Promise<QualityOption[]> => {
|
|
17
|
-
// Return cached result if available to avoid repeated network calls
|
|
18
|
-
if (qualitiesCache[m3u8Url]) {
|
|
19
|
-
return qualitiesCache[m3u8Url];
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
try {
|
|
23
|
-
const res = await fetch(m3u8Url);
|
|
24
|
-
const text = await res.text();
|
|
25
|
-
const qualities: QualityOption[] = [];
|
|
26
|
-
const lines = text.split('\n');
|
|
27
|
-
|
|
28
|
-
for (let i = 0; i < lines.length; i++) {
|
|
29
|
-
if (lines?.[i]?.includes('#EXT-X-STREAM-INF')) {
|
|
30
|
-
// Example line:
|
|
31
|
-
// #EXT-X-STREAM-INF:BANDWIDTH=800000,RESOLUTION=640x360,...
|
|
32
|
-
const resolutionMatch = lines?.[i]?.match(/RESOLUTION=\d+x(\d+)/);
|
|
33
|
-
const url = lines[i + 1]?.trim();
|
|
34
|
-
if (resolutionMatch && url) {
|
|
35
|
-
qualities.push({ quality: `${resolutionMatch[1]}p`, url });
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Cache the result (even if empty) so we don't re-fetch for this URL
|
|
41
|
-
qualitiesCache[m3u8Url] = qualities;
|
|
42
|
-
|
|
43
|
-
return qualities;
|
|
44
|
-
} catch (error) {
|
|
45
|
-
console.error('Error fetching video qualities:', error);
|
|
46
|
-
return [];
|
|
47
|
-
}
|
|
48
|
-
};
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { useCallback, useMemo } from 'react';
|
|
2
|
-
import { Gesture } from 'react-native-gesture-handler';
|
|
3
|
-
import { GESTURE_MAX_DURATION } from './videoControlsConstants';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Create a tap gesture handler
|
|
7
|
-
*/
|
|
8
|
-
export const useCreateTapGesture = (
|
|
9
|
-
isInOverlay: (x: number, y: number) => boolean,
|
|
10
|
-
isLocked: boolean,
|
|
11
|
-
handleLockedTap: () => void
|
|
12
|
-
) => {
|
|
13
|
-
return useCallback(
|
|
14
|
-
(onAction: () => void, numberOfTaps = 1) =>
|
|
15
|
-
Gesture.Tap()
|
|
16
|
-
.maxDuration(GESTURE_MAX_DURATION)
|
|
17
|
-
.numberOfTaps(numberOfTaps)
|
|
18
|
-
.onStart(({ x, y }) => {
|
|
19
|
-
if (isInOverlay(x, y)) return;
|
|
20
|
-
if (isLocked) {
|
|
21
|
-
handleLockedTap();
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
onAction();
|
|
25
|
-
})
|
|
26
|
-
.runOnJS(true),
|
|
27
|
-
[isInOverlay, isLocked, handleLockedTap]
|
|
28
|
-
);
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Create combined gesture (single tap and double tap)
|
|
33
|
-
*/
|
|
34
|
-
export const useCombinedGesture = (
|
|
35
|
-
singleTap: ReturnType<typeof Gesture.Tap>,
|
|
36
|
-
doubleTap: ReturnType<typeof Gesture.Tap>
|
|
37
|
-
) => {
|
|
38
|
-
return useMemo(
|
|
39
|
-
() => Gesture.Exclusive(doubleTap, singleTap),
|
|
40
|
-
[doubleTap, singleTap]
|
|
41
|
-
);
|
|
42
|
-
};
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { useMemo, useCallback } from 'react';
|
|
2
|
-
import { Dimensions } from 'react-native';
|
|
3
|
-
import {
|
|
4
|
-
OVERLAY_RIGHT_OFFSET,
|
|
5
|
-
OVERLAY_BOTTOM_OFFSET,
|
|
6
|
-
} from './videoControlsConstants';
|
|
7
|
-
|
|
8
|
-
const { width } = Dimensions.get('window');
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Calculate overlay thresholds
|
|
12
|
-
*/
|
|
13
|
-
export const useOverlayThresholds = (videoHeight: number) => {
|
|
14
|
-
const rightThreshold = useMemo(() => width - OVERLAY_RIGHT_OFFSET, []);
|
|
15
|
-
|
|
16
|
-
const bottomThreshold = useMemo(
|
|
17
|
-
() => videoHeight - OVERLAY_BOTTOM_OFFSET,
|
|
18
|
-
[videoHeight]
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
return { rightThreshold, bottomThreshold };
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Check if coordinates are in overlay area
|
|
26
|
-
*/
|
|
27
|
-
export const useIsInOverlay = (
|
|
28
|
-
rightThreshold: number,
|
|
29
|
-
bottomThreshold: number
|
|
30
|
-
) => {
|
|
31
|
-
return useCallback(
|
|
32
|
-
(x: number, y: number) => x > rightThreshold || y > bottomThreshold,
|
|
33
|
-
[rightThreshold, bottomThreshold]
|
|
34
|
-
);
|
|
35
|
-
};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Video Controls Constants
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export const GESTURE_MAX_DURATION = 300;
|
|
6
|
-
export const PAUSE_ICON_TIMEOUT = 800;
|
|
7
|
-
export const LIKE_ANIM_TIMEOUT = 1200;
|
|
8
|
-
export const UNLOCK_MODAL_DELAY = 500;
|
|
9
|
-
export const OVERLAY_RIGHT_OFFSET = 80;
|
|
10
|
-
export const OVERLAY_BOTTOM_OFFSET = 150;
|
|
11
|
-
|
|
12
|
-
export const videoControlsStyles = {
|
|
13
|
-
hideForward: true,
|
|
14
|
-
hideDuration: true,
|
|
15
|
-
hideFullscreen: true,
|
|
16
|
-
hidePlayPause: true,
|
|
17
|
-
hideNavigationBarOnFullScreenMode: true,
|
|
18
|
-
hideNotificationBarOnFullScreenMode: true,
|
|
19
|
-
hideNext: true,
|
|
20
|
-
hidePosition: true,
|
|
21
|
-
hidePrevious: true,
|
|
22
|
-
hideRewind: true,
|
|
23
|
-
hideSeekBar: true,
|
|
24
|
-
hideSettingButton: true,
|
|
25
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './timeoutUtils';
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type MutableRefObject } from 'react';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Safely clears a timeout stored in a ref
|
|
5
|
-
* @param ref - React ref containing the timeout
|
|
6
|
-
*/
|
|
7
|
-
export const clearTimeoutSafely = (
|
|
8
|
-
ref: MutableRefObject<NodeJS.Timeout | null>
|
|
9
|
-
): void => {
|
|
10
|
-
if (ref.current) {
|
|
11
|
-
clearTimeout(ref.current);
|
|
12
|
-
ref.current = null;
|
|
13
|
-
}
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Safely sets a timeout and stores it in a ref, clearing any existing timeout first
|
|
18
|
-
* @param ref - React ref to store the timeout
|
|
19
|
-
* @param callback - Function to execute after delay
|
|
20
|
-
* @param delay - Delay in milliseconds
|
|
21
|
-
*/
|
|
22
|
-
export const setTimeoutSafely = (
|
|
23
|
-
ref: MutableRefObject<NodeJS.Timeout | null>,
|
|
24
|
-
callback: () => void,
|
|
25
|
-
delay: number
|
|
26
|
-
): void => {
|
|
27
|
-
clearTimeoutSafely(ref);
|
|
28
|
-
ref.current = setTimeout(callback, delay);
|
|
29
|
-
};
|