@zezosoft/zezo-ott-react-native-ui-kit 1.3.6 → 1.3.8
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/README.md +40 -36
- package/lib/module/components/Content/Card/components/AdsPoster.js +40 -55
- package/lib/module/components/Content/Card/components/AdsPoster.js.map +1 -1
- package/lib/module/components/Content/Card/components/CardPoster.js +81 -107
- package/lib/module/components/Content/Card/components/CardPoster.js.map +1 -1
- package/lib/module/components/Content/Card/components/ThumbnailCard.js +48 -70
- package/lib/module/components/Content/Card/components/ThumbnailCard.js.map +1 -1
- package/lib/module/components/Search/components/SearchCard.js +2 -2
- package/lib/module/components/Search/components/SearchCard.js.map +1 -1
- package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts +1 -1
- package/lib/typescript/src/components/Content/Card/components/AdsPoster.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/components/CardPoster.d.ts.map +1 -1
- package/lib/typescript/src/components/Content/Card/components/ThumbnailCard.d.ts +1 -1
- package/lib/typescript/src/components/Content/Card/components/ThumbnailCard.d.ts.map +1 -1
- package/lib/typescript/src/components/Search/components/SearchCard.d.ts.map +1 -1
- package/package.json +1 -3
- package/lib/module/utils/colorUtils.js +0 -68
- package/lib/module/utils/colorUtils.js.map +0 -1
- package/lib/typescript/src/utils/colorUtils.d.ts +0 -19
- package/lib/typescript/src/utils/colorUtils.d.ts.map +0 -1
- 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 -354
- package/src/components/Account/index.ts +0 -6
- package/src/components/Alert/AlertDialog.tsx +0 -253
- package/src/components/Alert/UAAlert.tsx +0 -176
- package/src/components/Alert/index.ts +0 -7
- package/src/components/Auth/AuthProvider/AuthProvider.tsx +0 -412
- package/src/components/Auth/One/ForgotPassword/ForgotPassword.tsx +0 -333
- package/src/components/Auth/One/Login/LoginWithEmail.tsx +0 -449
- package/src/components/Auth/One/Login/LoginWithPhone.tsx +0 -309
- package/src/components/Auth/One/OTP/OTP.tsx +0 -539
- package/src/components/Auth/One/QrLogin/QrLogin.tsx +0 -329
- package/src/components/Auth/One/QrLogin/components/index.ts +0 -8
- package/src/components/Auth/One/QrLogin/components/qr-scanner-fallback.tsx +0 -158
- package/src/components/Auth/One/QrLogin/components/qr-scanner-frame.tsx +0 -207
- package/src/components/Auth/One/QrLogin/components/qr-scanner-header.tsx +0 -65
- package/src/components/Auth/One/QrLogin/components/qr-scanner-intro.tsx +0 -255
- package/src/components/Auth/One/QrLogin/components/qr-scanner-overlay.tsx +0 -291
- package/src/components/Auth/One/SignUp/SignUp.tsx +0 -470
- package/src/components/Auth/One/SplashScreen/SplashScreen.tsx +0 -229
- package/src/components/Auth/One/SplashScreen/components/SplashImage/SplashImage.tsx +0 -92
- package/src/components/Auth/One/SplashScreen/components/SplashLottie/SplashLottie.tsx +0 -129
- package/src/components/Auth/One/SplashScreen/components/SplashVideo/SplashVideo.tsx +0 -172
- package/src/components/Auth/One/SplashScreen/utils/splashUtils.ts +0 -23
- package/src/components/Auth/One/index.ts +0 -24
- package/src/components/Auth/Two/AuthHeader/AuthHeader.tsx +0 -130
- package/src/components/Auth/Two/ForgotPassword/ForgotPassword.tsx +0 -331
- package/src/components/Auth/Two/Login/EmailOrPhoneLogin.tsx +0 -612
- package/src/components/Auth/Two/OTP/OTP.tsx +0 -504
- package/src/components/Auth/Two/SignUp/SignUp.tsx +0 -439
- package/src/components/Auth/Two/index.ts +0 -20
- package/src/components/Auth/index.ts +0 -16
- package/src/components/BackgroundLayout/One/One.tsx +0 -184
- package/src/components/BackgroundLayout/Two/Two.tsx +0 -65
- package/src/components/BackgroundLayout/index.ts +0 -14
- package/src/components/BlogView/BlogView.tsx +0 -282
- 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 -204
- package/src/components/BottomSheet/BottomSheetOne.tsx +0 -223
- package/src/components/BottomSheet/index.ts +0 -9
- package/src/components/Button/BackBtn.tsx +0 -149
- package/src/components/Button/MenuBtn.tsx +0 -220
- package/src/components/Button/PrimaryBtn.tsx +0 -123
- package/src/components/Button/SecondaryBtn.tsx +0 -123
- package/src/components/Button/TextButton.tsx +0 -150
- package/src/components/Button/index.ts +0 -18
- package/src/components/Button/types.ts +0 -33
- 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 -607
- package/src/components/Content/Card/Sliders/Styles/One.tsx +0 -490
- package/src/components/Content/Card/Sliders/Styles/Three.tsx +0 -1017
- package/src/components/Content/Card/Sliders/Styles/Two.tsx +0 -395
- package/src/components/Content/Card/Sliders/index.ts +0 -18
- package/src/components/Content/Card/Styles/Five.tsx +0 -367
- package/src/components/Content/Card/Styles/Four.tsx +0 -366
- package/src/components/Content/Card/Styles/One.tsx +0 -372
- package/src/components/Content/Card/Styles/RotateInOut.tsx +0 -413
- package/src/components/Content/Card/Styles/Six.tsx +0 -378
- package/src/components/Content/Card/Styles/Three.tsx +0 -312
- package/src/components/Content/Card/Styles/TopTen.tsx +0 -402
- package/src/components/Content/Card/Styles/Two.tsx +0 -404
- package/src/components/Content/Card/components/AdsPoster.tsx +0 -207
- package/src/components/Content/Card/components/CardPoster.tsx +0 -377
- package/src/components/Content/Card/components/LiveBadge.tsx +0 -125
- package/src/components/Content/Card/components/NavigateToMore.tsx +0 -97
- package/src/components/Content/Card/components/RentOrBuyIcon.tsx +0 -134
- package/src/components/Content/Card/components/ShowAllButton.tsx +0 -92
- package/src/components/Content/Card/components/ThumbnailCard.tsx +0 -219
- package/src/components/Content/Card/components/index.ts +0 -12
- package/src/components/Content/Card/index.ts +0 -31
- package/src/components/Content/Content.tsx +0 -338
- package/src/components/Content/Sections.tsx +0 -239
- package/src/components/Content/types.ts +0 -180
- package/src/components/ContentView/MoreContentList.tsx +0 -330
- package/src/components/ContentView/One/ContentViewOne.tsx +0 -251
- package/src/components/ContentView/One/components/CastCard.tsx +0 -266
- package/src/components/ContentView/One/components/HeroBanner.tsx +0 -413
- package/src/components/ContentView/One/components/MiniInfo.tsx +0 -343
- package/src/components/ContentView/One/components/Title.tsx +0 -149
- package/src/components/ContentView/Two/ContentViewTwo.tsx +0 -332
- package/src/components/ContentView/Two/components/Details.tsx +0 -196
- package/src/components/ContentView/Two/components/HeroBanner.tsx +0 -267
- package/src/components/ContentView/Two/components/LikeShareActions.tsx +0 -125
- package/src/components/ContentView/Two/components/MoreLikeThisContentList .tsx +0 -308
- package/src/components/ContentView/Two/components/PlayOrTrailer.tsx +0 -162
- package/src/components/ContentView/Two/components/SectionTabs.tsx +0 -181
- package/src/components/ContentView/Two/components/Title.tsx +0 -229
- package/src/components/ContentView/Two/components/index.ts +0 -12
- package/src/components/ContentView/index.ts +0 -13
- package/src/components/ContentView/shared/AboutSection.tsx +0 -226
- package/src/components/ContentView/shared/EpisodeCard.tsx +0 -600
- package/src/components/ContentView/shared/GenreTags.tsx +0 -189
- package/src/components/ContentView/shared/PlayButton.tsx +0 -52
- package/src/components/ContentView/shared/TrailerButton.tsx +0 -76
- package/src/components/Fallbacks/NoContentFallback.tsx +0 -175
- package/src/components/Fallbacks/NotFoundFallback.tsx +0 -94
- package/src/components/Fallbacks/index.ts +0 -7
- package/src/components/Headers/AppHeader.tsx +0 -151
- package/src/components/Headers/Four.tsx +0 -84
- package/src/components/Headers/One.tsx +0 -115
- package/src/components/Headers/Three.tsx +0 -137
- package/src/components/Headers/Two.tsx +0 -101
- package/src/components/Headers/index.ts +0 -34
- package/src/components/Input/Input.ts +0 -18
- package/src/components/Input/InputOne.tsx +0 -265
- package/src/components/Input/InputThree.tsx +0 -205
- package/src/components/Input/InputTwo.tsx +0 -217
- package/src/components/Input/PhoneInput/One/One.tsx +0 -415
- package/src/components/Input/PhoneInput/Two/Two.tsx +0 -406
- package/src/components/Input/PhoneInput/index.ts +0 -14
- package/src/components/Keyboard/HideKeyboard.tsx +0 -91
- package/src/components/Loader/Loader.tsx +0 -49
- package/src/components/Logo/Logo.tsx +0 -150
- package/src/components/NewRelease/NewReleaseSheet.tsx +0 -260
- package/src/components/NewRelease/index.ts +0 -6
- package/src/components/Reels/ReelsSeries/MediaControls/BottomControls.tsx +0 -226
- package/src/components/Reels/ReelsSeries/MediaControls/MediaControlsProvider.tsx +0 -324
- package/src/components/Reels/ReelsSeries/MediaControls/MiddleControls.tsx +0 -201
- package/src/components/Reels/ReelsSeries/MediaControls/RightControls.tsx +0 -100
- package/src/components/Reels/ReelsSeries/MediaControls/TopControls.tsx +0 -168
- package/src/components/Reels/ReelsSeries/Model/DetailsModal.tsx +0 -207
- package/src/components/Reels/ReelsSeries/Model/SettingModal.tsx +0 -151
- package/src/components/Reels/ReelsSeries/Model/UnlockModal.tsx +0 -159
- package/src/components/Reels/ReelsSeries/ReelsSeries.tsx +0 -278
- package/src/components/Reels/ReelsSeries/ReelsSeriesItem.tsx +0 -569
- package/src/components/Reels/ReelsSeries/components/AnimatedThreeLines.tsx +0 -189
- package/src/components/Reels/ReelsSeries/components/Episodes.tsx +0 -159
- package/src/components/Reels/ReelsSeries/components/GradientOverlay.tsx +0 -46
- package/src/components/Reels/ReelsSeries/components/Like.tsx +0 -45
- package/src/components/Reels/ReelsSeries/components/RotatingLoader.tsx +0 -84
- package/src/components/Reels/ReelsSeries/components/Synopsis.tsx +0 -338
- package/src/components/Reels/ReelsSeries/components/VideoControls/QualityControl.tsx +0 -185
- package/src/components/Reels/ReelsSeries/components/VideoControls/SpeedControl.tsx +0 -77
- package/src/components/Reels/ReelsSeries/components/VideoControls/index.ts +0 -7
- package/src/components/Reels/ReelsSeries/types.ts +0 -78
- package/src/components/Reels/ReelsSeries/useReelsWatchProgress.ts +0 -90
- package/src/components/Reels/ReelsSeries/utils/quality.ts +0 -72
- package/src/components/Reels/index.ts +0 -9
- package/src/components/Reels/utils/Controls/gestureUtils.ts +0 -46
- package/src/components/Reels/utils/Controls/index.ts +0 -9
- package/src/components/Reels/utils/Controls/overlayUtils.ts +0 -40
- package/src/components/Reels/utils/Controls/videoControlsConstants.ts +0 -30
- package/src/components/Reels/utils/Controls/videoRef.ts +0 -9
- package/src/components/Reels/utils/index.ts +0 -6
- package/src/components/Reels/utils/timeoutUtils.ts +0 -34
- package/src/components/Search/One.tsx +0 -262
- package/src/components/Search/components/RecentSearchesSection.tsx +0 -181
- package/src/components/Search/components/SearchCard.tsx +0 -285
- package/src/components/Search/index.ts +0 -16
- package/src/components/Settings/AppSettings.tsx +0 -442
- package/src/components/Settings/index.ts +0 -6
- package/src/components/Subscription/SubOne.tsx +0 -423
- package/src/components/Subscription/components/SubsDetailsModal.tsx +0 -347
- package/src/components/Subscription/components/SubscriptionCard.tsx +0 -342
- package/src/components/Subscription/index.ts +0 -12
- package/src/components/TabBar/One.tsx +0 -145
- package/src/components/TabBar/Three.tsx +0 -162
- package/src/components/TabBar/Two.tsx +0 -179
- package/src/components/TabBar/index.ts +0 -20
- package/src/components/Text/Text.tsx +0 -90
- package/src/components/Text/index.ts +0 -6
- package/src/components/User/DeviceSessions/DeviceSessions.tsx +0 -468
- package/src/components/User/ProfileUpdate/ProfileUpdate.tsx +0 -293
- package/src/components/User/PurchaseHistory/PurchaseHistory.tsx +0 -504
- package/src/components/User/WatchHistory/WatchHistory.tsx +0 -214
- package/src/components/User/WatchLater/WatchLater.tsx +0 -400
- package/src/components/User/components/UserAvatar.tsx +0 -121
- package/src/components/User/components/UserSection.tsx +0 -218
- package/src/components/User/index.ts +0 -18
- package/src/components/View/View.tsx +0 -38
- package/src/components/View/index.ts +0 -6
- package/src/components/common/AppStatusBar.tsx +0 -57
- package/src/components/common/index.ts +0 -1
- package/src/components/index.ts +0 -30
- package/src/components/layout/SafeAreaWrapper.tsx +0 -50
- package/src/components/layout/index.ts +0 -6
- package/src/constants/dummySections.ts +0 -103
- package/src/hooks/Images/index.ts +0 -6
- package/src/hooks/Images/useImageLoader.ts +0 -209
- package/src/hooks/index.ts +0 -16
- package/src/hooks/useAdTracking.ts +0 -354
- package/src/hooks/useCards.ts +0 -247
- package/src/hooks/useDebounce.ts +0 -40
- package/src/hooks/useKeyboard.ts +0 -43
- package/src/hooks/useNavigationMode.ts +0 -48
- package/src/hooks/usePaginatedSection.ts +0 -108
- package/src/hooks/usePrevious.ts +0 -28
- package/src/hooks/useSafeCallback.ts +0 -29
- package/src/hooks/useSkeletonItems.ts +0 -30
- package/src/hooks/useSplashCache.ts +0 -245
- package/src/index.tsx +0 -9
- package/src/store/RecentSearchesStore.ts +0 -72
- package/src/store/splashStore.ts +0 -86
- package/src/store/storage.ts +0 -29
- package/src/theme/ThemeContext.ts +0 -19
- package/src/theme/ThemeProvider.tsx +0 -87
- package/src/theme/hooks/index.ts +0 -6
- package/src/theme/hooks/useTheme.ts +0 -118
- package/src/theme/index.ts +0 -8
- package/src/theme/store/theme.ts +0 -50
- package/src/theme/themes.ts +0 -262
- package/src/theme/utils/cleanColors.ts +0 -71
- package/src/theme/utils/toRgba.ts +0 -150
- package/src/types/content/content-view.types.ts +0 -209
- package/src/types/hook/index.ts +0 -6
- package/src/types/hook/usePaginatedSection.ts +0 -20
- package/src/types/index.ts +0 -10
- package/src/types/navigation.ts +0 -17
- package/src/types/sections/index.ts +0 -87
- package/src/types/user.ts +0 -18
- package/src/utils/Display.ts +0 -15
- package/src/utils/Formater.ts +0 -33
- package/src/utils/SizeMatters.ts +0 -8
- package/src/utils/Spacing.ts +0 -27
- package/src/utils/colorUtils.ts +0 -70
- package/src/utils/imageValidation.ts +0 -36
- package/src/utils/interaction.ts +0 -19
package/src/hooks/useCards.ts
DELETED
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Global Card Hook (No duplicates + single data key)
|
|
8
|
-
*
|
|
9
|
-
* Provides a unified interface for managing card data with:
|
|
10
|
-
* - Automatic deduplication
|
|
11
|
-
* - Skeleton loading states
|
|
12
|
-
* - Pagination support
|
|
13
|
-
* - Optimized performance
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { useMemo, useCallback } from 'react';
|
|
17
|
-
import type { IContentData } from '@zezosoft/zezo-ott-api-client';
|
|
18
|
-
import { usePaginatedSection } from './usePaginatedSection';
|
|
19
|
-
import type { IAdItem, MoreFetchData } from '../types';
|
|
20
|
-
import { dummyContentData } from '../constants/dummySections';
|
|
21
|
-
|
|
22
|
-
export type CardSource =
|
|
23
|
-
{ data: (IContentData | IAdItem)[] } | (IContentData | IAdItem)[] | null;
|
|
24
|
-
|
|
25
|
-
export type UseCardsOptions = {
|
|
26
|
-
sectionId: string;
|
|
27
|
-
data?: CardSource;
|
|
28
|
-
fetchMore?: MoreFetchData<IContentData>;
|
|
29
|
-
loading?: boolean;
|
|
30
|
-
initialSkeleton?: number;
|
|
31
|
-
pagingSkeleton?: number;
|
|
32
|
-
adsRender?: boolean; // If false, ads will be filtered out from listData
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
export type UseCardsReturn = {
|
|
36
|
-
listData: (IContentData | IAdItem)[]; // ✔ Mixed array of content and ads
|
|
37
|
-
pagination: {
|
|
38
|
-
hasNextPage: boolean;
|
|
39
|
-
nextPage: number | null;
|
|
40
|
-
} | null;
|
|
41
|
-
isPaging: boolean;
|
|
42
|
-
hasMore: boolean;
|
|
43
|
-
loadMore: (page: number | null) => Promise<void>;
|
|
44
|
-
isEmpty: boolean;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
// -----------------------------------------------------------
|
|
48
|
-
// Constants
|
|
49
|
-
// -----------------------------------------------------------
|
|
50
|
-
|
|
51
|
-
const DEFAULT_INITIAL_SKELETON = 5;
|
|
52
|
-
const DEFAULT_PAGING_SKELETON = 3;
|
|
53
|
-
|
|
54
|
-
// -----------------------------------------------------------
|
|
55
|
-
// Helpers
|
|
56
|
-
// -----------------------------------------------------------
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Normalizes different data source formats into a single array
|
|
60
|
-
*/
|
|
61
|
-
const normalize = (src: CardSource): (IContentData | IAdItem)[] => {
|
|
62
|
-
if (!src) return [];
|
|
63
|
-
if (Array.isArray(src)) return src;
|
|
64
|
-
return src.data ?? [];
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Removes duplicate items by _id using Map for O(n) performance
|
|
69
|
-
* Preserves order of first occurrence
|
|
70
|
-
* Handles both IContentData and IAdItem types
|
|
71
|
-
*/
|
|
72
|
-
const uniqueById = (
|
|
73
|
-
list: (IContentData | IAdItem)[]
|
|
74
|
-
): (IContentData | IAdItem)[] => {
|
|
75
|
-
if (list.length === 0) return [];
|
|
76
|
-
|
|
77
|
-
const seen = new Map<string, IContentData | IAdItem>();
|
|
78
|
-
const result: (IContentData | IAdItem)[] = [];
|
|
79
|
-
|
|
80
|
-
for (let i = 0; i < list.length; i++) {
|
|
81
|
-
const item = list[i];
|
|
82
|
-
if (!item) continue;
|
|
83
|
-
|
|
84
|
-
// Handle ads - check for type property and use appropriate ID field
|
|
85
|
-
if ('type' in item && item.type === 'ads') {
|
|
86
|
-
const adItem = item as IAdItem;
|
|
87
|
-
// Ads might have _id (from IServeAd) or use mediaUrl as identifier
|
|
88
|
-
let id: string;
|
|
89
|
-
if ('_id' in adItem && adItem._id) {
|
|
90
|
-
id = String(adItem._id);
|
|
91
|
-
} else if ('mediaUrl' in adItem && adItem.mediaUrl) {
|
|
92
|
-
id = `ad-${adItem.mediaUrl}`;
|
|
93
|
-
} else {
|
|
94
|
-
id = `ad-${i}`;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
if (!seen.has(id)) {
|
|
98
|
-
seen.set(id, adItem);
|
|
99
|
-
result.push(adItem);
|
|
100
|
-
}
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Handle content items
|
|
105
|
-
const contentItem = item as IContentData;
|
|
106
|
-
if (!contentItem?._id) continue; // Skip items without valid IDs
|
|
107
|
-
|
|
108
|
-
const id = String(contentItem._id);
|
|
109
|
-
if (!seen.has(id)) {
|
|
110
|
-
seen.set(id, contentItem);
|
|
111
|
-
result.push(contentItem);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
return result;
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Creates skeleton items for loading states
|
|
120
|
-
* Memoized by count to avoid unnecessary recreations
|
|
121
|
-
* Returns IContentData[] for skeleton loading (ads don't need skeletons)
|
|
122
|
-
*/
|
|
123
|
-
const createSkeletonItems = (count: number, prefix: string): IContentData[] => {
|
|
124
|
-
if (count <= 0) return [];
|
|
125
|
-
return Array.from({ length: count }, (_, i) =>
|
|
126
|
-
dummyContentData(`${prefix}-${i}`)
|
|
127
|
-
);
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
// -----------------------------------------------------------
|
|
131
|
-
// Hook
|
|
132
|
-
// -----------------------------------------------------------
|
|
133
|
-
|
|
134
|
-
export function useCards({
|
|
135
|
-
sectionId,
|
|
136
|
-
data,
|
|
137
|
-
fetchMore,
|
|
138
|
-
loading = false,
|
|
139
|
-
initialSkeleton = DEFAULT_INITIAL_SKELETON,
|
|
140
|
-
pagingSkeleton = DEFAULT_PAGING_SKELETON,
|
|
141
|
-
adsRender = false,
|
|
142
|
-
}: UseCardsOptions): UseCardsReturn {
|
|
143
|
-
// Normalize input data
|
|
144
|
-
const baseItems = useMemo(() => normalize(data ?? { data: [] }), [data]);
|
|
145
|
-
|
|
146
|
-
// Use pagination hook for data management
|
|
147
|
-
const {
|
|
148
|
-
data: list,
|
|
149
|
-
pagination,
|
|
150
|
-
loadMoreData,
|
|
151
|
-
isPaginating,
|
|
152
|
-
hasMore,
|
|
153
|
-
} = usePaginatedSection<IContentData | IAdItem>(
|
|
154
|
-
sectionId,
|
|
155
|
-
fetchMore,
|
|
156
|
-
baseItems,
|
|
157
|
-
loading
|
|
158
|
-
);
|
|
159
|
-
|
|
160
|
-
// If no fetchMore function is provided, explicitly disable further pagination
|
|
161
|
-
const safePagination = useMemo(
|
|
162
|
-
() =>
|
|
163
|
-
fetchMore
|
|
164
|
-
? pagination
|
|
165
|
-
: pagination
|
|
166
|
-
? { ...pagination, hasNextPage: false, nextPage: null }
|
|
167
|
-
: pagination,
|
|
168
|
-
[pagination, fetchMore]
|
|
169
|
-
);
|
|
170
|
-
|
|
171
|
-
const safeHasMore = fetchMore ? hasMore : false;
|
|
172
|
-
|
|
173
|
-
// Apply deduplication to the list (handles both content and ads)
|
|
174
|
-
const uniqueList = useMemo(
|
|
175
|
-
() => uniqueById(list as (IContentData | IAdItem)[]),
|
|
176
|
-
[list]
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
// Memoize skeleton items - only recreate when count changes
|
|
180
|
-
const initialSkeletonItems = useMemo(
|
|
181
|
-
() => createSkeletonItems(initialSkeleton, 'sk'),
|
|
182
|
-
[initialSkeleton]
|
|
183
|
-
);
|
|
184
|
-
|
|
185
|
-
const pagingSkeletonItems = useMemo(
|
|
186
|
-
() => createSkeletonItems(pagingSkeleton, 'pagination-skeleton'),
|
|
187
|
-
[pagingSkeleton]
|
|
188
|
-
);
|
|
189
|
-
|
|
190
|
-
// Filter ads if adsRender is false
|
|
191
|
-
const filteredList = useMemo(() => {
|
|
192
|
-
if (adsRender) return uniqueList;
|
|
193
|
-
return uniqueList.filter(
|
|
194
|
-
(item): item is IContentData => item.type !== 'ads'
|
|
195
|
-
);
|
|
196
|
-
}, [uniqueList, adsRender]);
|
|
197
|
-
|
|
198
|
-
// Final data array for UI rendering
|
|
199
|
-
// Handles loading states and pagination skeletons
|
|
200
|
-
// Returns mixed array of IContentData | IAdItem (or only IContentData if adsRender is false)
|
|
201
|
-
const items = useMemo(() => {
|
|
202
|
-
// Show initial skeleton during initial load
|
|
203
|
-
if (loading) return initialSkeletonItems as (IContentData | IAdItem)[];
|
|
204
|
-
|
|
205
|
-
// Show data with pagination skeleton when loading more
|
|
206
|
-
if (isPaginating && filteredList.length > 0) {
|
|
207
|
-
return [
|
|
208
|
-
...filteredList,
|
|
209
|
-
...(pagingSkeletonItems as (IContentData | IAdItem)[]),
|
|
210
|
-
];
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// Return filtered list (with or without ads based on adsRender)
|
|
214
|
-
return filteredList;
|
|
215
|
-
}, [
|
|
216
|
-
loading,
|
|
217
|
-
isPaginating,
|
|
218
|
-
filteredList,
|
|
219
|
-
initialSkeletonItems,
|
|
220
|
-
pagingSkeletonItems,
|
|
221
|
-
]);
|
|
222
|
-
|
|
223
|
-
// Determine if section is empty (only when not loading and no data)
|
|
224
|
-
const isEmpty = useMemo(
|
|
225
|
-
() => !loading && filteredList.length === 0,
|
|
226
|
-
[loading, filteredList.length]
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
// Memoize loadMore callback to prevent unnecessary re-renders
|
|
230
|
-
const handleLoadMore = useCallback(
|
|
231
|
-
async (page: number | null) => {
|
|
232
|
-
if (page && safeHasMore && !isPaginating) {
|
|
233
|
-
await loadMoreData(page);
|
|
234
|
-
}
|
|
235
|
-
},
|
|
236
|
-
[loadMoreData, safeHasMore, isPaginating]
|
|
237
|
-
);
|
|
238
|
-
|
|
239
|
-
return {
|
|
240
|
-
listData: items,
|
|
241
|
-
pagination: safePagination,
|
|
242
|
-
isPaging: isPaginating,
|
|
243
|
-
hasMore: safeHasMore,
|
|
244
|
-
loadMore: handleLoadMore,
|
|
245
|
-
isEmpty,
|
|
246
|
-
};
|
|
247
|
-
}
|
package/src/hooks/useDebounce.ts
DELETED
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useCallback, useRef, useEffect } from 'react';
|
|
7
|
-
|
|
8
|
-
export const useDebounce = (
|
|
9
|
-
callback: (value: string) => void,
|
|
10
|
-
delay: number
|
|
11
|
-
) => {
|
|
12
|
-
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
|
|
13
|
-
const callbackRef = useRef(callback);
|
|
14
|
-
|
|
15
|
-
// Update callback ref when it changes
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
callbackRef.current = callback;
|
|
18
|
-
}, [callback]);
|
|
19
|
-
|
|
20
|
-
// Cleanup on unmount
|
|
21
|
-
useEffect(() => {
|
|
22
|
-
return () => {
|
|
23
|
-
if (timeoutRef.current) {
|
|
24
|
-
clearTimeout(timeoutRef.current);
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
}, []);
|
|
28
|
-
|
|
29
|
-
return useCallback(
|
|
30
|
-
(value: string) => {
|
|
31
|
-
if (timeoutRef.current) {
|
|
32
|
-
clearTimeout(timeoutRef.current);
|
|
33
|
-
}
|
|
34
|
-
timeoutRef.current = setTimeout(() => {
|
|
35
|
-
callbackRef.current(value);
|
|
36
|
-
}, delay);
|
|
37
|
-
},
|
|
38
|
-
[delay]
|
|
39
|
-
);
|
|
40
|
-
};
|
package/src/hooks/useKeyboard.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useEffect, useState, useCallback, useMemo } from 'react';
|
|
7
|
-
import { Keyboard, Platform } from 'react-native';
|
|
8
|
-
|
|
9
|
-
export const useKeyboard = () => {
|
|
10
|
-
const [isKeyboardOpen, setKeyboardOpen] = useState(false);
|
|
11
|
-
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const showEvent =
|
|
14
|
-
Platform.OS === 'ios' ? 'keyboardWillShow' : 'keyboardDidShow';
|
|
15
|
-
const hideEvent =
|
|
16
|
-
Platform.OS === 'ios' ? 'keyboardWillHide' : 'keyboardDidHide';
|
|
17
|
-
|
|
18
|
-
const showListener = Keyboard.addListener(showEvent, () => {
|
|
19
|
-
setKeyboardOpen(true);
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
const hideListener = Keyboard.addListener(hideEvent, () => {
|
|
23
|
-
setKeyboardOpen(false);
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
return () => {
|
|
27
|
-
showListener.remove();
|
|
28
|
-
hideListener.remove();
|
|
29
|
-
};
|
|
30
|
-
}, []);
|
|
31
|
-
|
|
32
|
-
const hideKeyboard = useCallback(() => {
|
|
33
|
-
Keyboard.dismiss();
|
|
34
|
-
}, []);
|
|
35
|
-
|
|
36
|
-
return useMemo(
|
|
37
|
-
() => ({
|
|
38
|
-
isKeyboardOpen,
|
|
39
|
-
hideKeyboard,
|
|
40
|
-
}),
|
|
41
|
-
[isKeyboardOpen, hideKeyboard]
|
|
42
|
-
);
|
|
43
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useEffect, useState, useMemo } from 'react';
|
|
7
|
-
import NavigationMode from 'react-native-navigation-mode';
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Hook to detect Android navigation mode
|
|
11
|
-
* @returns {Object} Navigation mode info
|
|
12
|
-
* @returns {boolean} isGestureNav - true if using gesture navigation
|
|
13
|
-
*/
|
|
14
|
-
export const useNavigationMode = () => {
|
|
15
|
-
const [isThreeButtonNav, setIsThreeButtonNav] = useState(false);
|
|
16
|
-
|
|
17
|
-
useEffect(() => {
|
|
18
|
-
let mounted = true;
|
|
19
|
-
|
|
20
|
-
(async () => {
|
|
21
|
-
try {
|
|
22
|
-
const navMode = (await NavigationMode.getNavigationMode()) as {
|
|
23
|
-
navigationMode?: string;
|
|
24
|
-
mode?: string;
|
|
25
|
-
} | null;
|
|
26
|
-
const isThreeButton =
|
|
27
|
-
navMode?.navigationMode === 'THREE_BUTTON' ||
|
|
28
|
-
navMode?.mode === 'THREE_BUTTON';
|
|
29
|
-
if (mounted) {
|
|
30
|
-
setIsThreeButtonNav(isThreeButton);
|
|
31
|
-
}
|
|
32
|
-
} catch {
|
|
33
|
-
// Navigation mode detection error ignored
|
|
34
|
-
}
|
|
35
|
-
})();
|
|
36
|
-
|
|
37
|
-
return () => {
|
|
38
|
-
mounted = false;
|
|
39
|
-
};
|
|
40
|
-
}, []);
|
|
41
|
-
|
|
42
|
-
return useMemo(
|
|
43
|
-
() => ({
|
|
44
|
-
isGestureNav: !isThreeButtonNav,
|
|
45
|
-
}),
|
|
46
|
-
[isThreeButtonNav]
|
|
47
|
-
);
|
|
48
|
-
};
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import React, { useCallback, useState } from 'react';
|
|
7
|
-
import type { MoreFetchData } from '../types';
|
|
8
|
-
|
|
9
|
-
export function usePaginatedSection<T>(
|
|
10
|
-
sectionId: string,
|
|
11
|
-
fetchFn?: MoreFetchData<T>,
|
|
12
|
-
initialData: T[] = [],
|
|
13
|
-
isLoading?: boolean
|
|
14
|
-
) {
|
|
15
|
-
const [data, setData] = useState<T[]>(initialData);
|
|
16
|
-
const [pagination, setPagination] = useState<{
|
|
17
|
-
hasNextPage: boolean;
|
|
18
|
-
nextPage: number | null;
|
|
19
|
-
}>({
|
|
20
|
-
hasNextPage: true,
|
|
21
|
-
nextPage: 2,
|
|
22
|
-
});
|
|
23
|
-
const [isPaginating, setIsPaginating] = useState(false);
|
|
24
|
-
|
|
25
|
-
// Sync initial data on mount or loading complete
|
|
26
|
-
React.useEffect(() => {
|
|
27
|
-
if (isLoading) return;
|
|
28
|
-
|
|
29
|
-
// Check if initialData prefix differs from current data
|
|
30
|
-
const hasLengthChangedToEmpty = initialData.length === 0 && data.length > 0;
|
|
31
|
-
const hasPrefixChanged =
|
|
32
|
-
initialData.length > 0 &&
|
|
33
|
-
(data.length < initialData.length ||
|
|
34
|
-
initialData.some((item, idx) => item !== data[idx]));
|
|
35
|
-
|
|
36
|
-
if (hasLengthChangedToEmpty || hasPrefixChanged) {
|
|
37
|
-
setData(initialData);
|
|
38
|
-
setPagination({
|
|
39
|
-
hasNextPage: true,
|
|
40
|
-
nextPage: 2,
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}, [isLoading, initialData, data]);
|
|
44
|
-
|
|
45
|
-
const loadMoreData = useCallback(
|
|
46
|
-
async (page: number | null) => {
|
|
47
|
-
if (!page || isPaginating || !pagination.hasNextPage || !fetchFn) return;
|
|
48
|
-
|
|
49
|
-
setIsPaginating(true);
|
|
50
|
-
try {
|
|
51
|
-
const res = await fetchFn({
|
|
52
|
-
sectionId,
|
|
53
|
-
meta: {
|
|
54
|
-
hasNextPage: pagination.hasNextPage,
|
|
55
|
-
nextPage: page,
|
|
56
|
-
},
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
if (!res) {
|
|
60
|
-
setPagination({
|
|
61
|
-
hasNextPage: false,
|
|
62
|
-
nextPage: null,
|
|
63
|
-
});
|
|
64
|
-
return;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
if (!res.data || !res.meta?.pagination) {
|
|
68
|
-
console.warn(`⚠️ Invalid response for section: ${sectionId}`, res);
|
|
69
|
-
setPagination({
|
|
70
|
-
hasNextPage: false,
|
|
71
|
-
nextPage: null,
|
|
72
|
-
});
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
const { hasNextPage, nextPage } = res.meta.pagination;
|
|
77
|
-
|
|
78
|
-
setData((prev) => {
|
|
79
|
-
const existingIds = new Set(
|
|
80
|
-
(prev as { _id?: string | number }[]).map((item) => item._id)
|
|
81
|
-
);
|
|
82
|
-
const newItems = res.data.filter(
|
|
83
|
-
(item) => !existingIds.has((item as { _id?: string | number })._id)
|
|
84
|
-
);
|
|
85
|
-
return [...prev, ...newItems];
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
setPagination({
|
|
89
|
-
hasNextPage,
|
|
90
|
-
nextPage,
|
|
91
|
-
});
|
|
92
|
-
} catch (err) {
|
|
93
|
-
console.error(`❌ Error loading section [${sectionId}]:`, err);
|
|
94
|
-
} finally {
|
|
95
|
-
setIsPaginating(false);
|
|
96
|
-
}
|
|
97
|
-
},
|
|
98
|
-
[isPaginating, pagination.hasNextPage, fetchFn, sectionId]
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
return {
|
|
102
|
-
data,
|
|
103
|
-
pagination,
|
|
104
|
-
isPaginating,
|
|
105
|
-
hasMore: pagination.hasNextPage,
|
|
106
|
-
loadMoreData,
|
|
107
|
-
};
|
|
108
|
-
}
|
package/src/hooks/usePrevious.ts
DELETED
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useRef } from 'react';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Hook to get the previous value of a prop or state
|
|
10
|
-
* Optimized to avoid useEffect overhead
|
|
11
|
-
* @param value - The value to track
|
|
12
|
-
* @returns The previous value
|
|
13
|
-
*/
|
|
14
|
-
export function usePrevious<T>(value: T): T | undefined {
|
|
15
|
-
const ref = useRef<{ value: T; previous: T | undefined }>({
|
|
16
|
-
value,
|
|
17
|
-
previous: undefined,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// Update ref synchronously during render
|
|
21
|
-
const current = ref.current;
|
|
22
|
-
if (current.value !== value) {
|
|
23
|
-
current.previous = current.value;
|
|
24
|
-
current.value = value;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return current.previous;
|
|
28
|
-
}
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useCallback, useRef } from 'react';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Creates a safe press handler that checks disabled state.
|
|
10
|
-
* Supports both:
|
|
11
|
-
* - React Native onPress(event)
|
|
12
|
-
* - React Hook Form handleSubmit()
|
|
13
|
-
*/
|
|
14
|
-
export function useSafePressHandler(
|
|
15
|
-
onPress?: (() => Promise<void> | void) | undefined,
|
|
16
|
-
disabled = false
|
|
17
|
-
) {
|
|
18
|
-
const onPressRef = useRef(onPress);
|
|
19
|
-
onPressRef.current = onPress;
|
|
20
|
-
|
|
21
|
-
const disabledRef = useRef(disabled);
|
|
22
|
-
disabledRef.current = disabled;
|
|
23
|
-
|
|
24
|
-
return useCallback(async () => {
|
|
25
|
-
if (disabledRef.current || !onPressRef.current) return;
|
|
26
|
-
|
|
27
|
-
await onPressRef.current();
|
|
28
|
-
}, []);
|
|
29
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @author Naresh Dhamu
|
|
3
|
-
* @LastModified Mon 13 Jul 2026 at 10:13 AM
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { useMemo, useRef } from 'react';
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Hook to create skeleton items array
|
|
10
|
-
* Memoized to prevent unnecessary recreations
|
|
11
|
-
* Generator function is stored in ref to avoid dependency issues
|
|
12
|
-
*/
|
|
13
|
-
export function useSkeletonItems<T = unknown>(
|
|
14
|
-
count: number,
|
|
15
|
-
generator?: (index: number) => T
|
|
16
|
-
): T[] {
|
|
17
|
-
const generatorRef = useRef(generator);
|
|
18
|
-
generatorRef.current = generator;
|
|
19
|
-
|
|
20
|
-
return useMemo(() => {
|
|
21
|
-
if (count <= 0) return [];
|
|
22
|
-
if (generatorRef.current) {
|
|
23
|
-
return Array.from({ length: count }, (_, i) => generatorRef.current!(i));
|
|
24
|
-
}
|
|
25
|
-
return Array.from({ length: count }, (_, i) => ({
|
|
26
|
-
_id: `skeleton-${i}`,
|
|
27
|
-
isSkeleton: true,
|
|
28
|
-
})) as T[];
|
|
29
|
-
}, [count]);
|
|
30
|
-
}
|