mirror of
https://github.com/p-stream/p-stream.git
synced 2026-03-31 05:38:44 +00:00
optimize trakt loading for carousel view
This commit is contained in:
parent
0603c8cb7c
commit
8cbe8f986a
3 changed files with 58 additions and 28 deletions
|
|
@ -84,6 +84,7 @@ export function MoreContent({ onShowDetails }: MoreContentProps) {
|
|||
mediaTitle: recommendationSources.find(
|
||||
(s) => s.id === selectedRecommendationId,
|
||||
)?.title,
|
||||
isCarouselView: false,
|
||||
});
|
||||
|
||||
// Handle content visibility
|
||||
|
|
@ -184,17 +185,19 @@ export function MoreContent({ onShowDetails }: MoreContentProps) {
|
|||
<div className="animate-pulse">
|
||||
<div className="h-8 bg-mediaCard-hoverBackground rounded w-1/4 mb-8" />
|
||||
<MediaGrid>
|
||||
{Array.from({ length: 20 }).map((_, _i) => (
|
||||
<div
|
||||
key={`loading-skeleton-${Math.random().toString(36).substring(7)}`}
|
||||
className="relative group cursor-default user-select-none rounded-xl p-2 bg-transparent"
|
||||
>
|
||||
<div className="animate-pulse">
|
||||
<div className="w-full aspect-[2/3] bg-mediaCard-hoverBackground rounded-lg" />
|
||||
<div className="mt-2 h-4 bg-mediaCard-hoverBackground rounded w-3/4" />
|
||||
{Array(20)
|
||||
.fill(null)
|
||||
.map(() => (
|
||||
<div
|
||||
key={`loading-skeleton-${Math.random().toString(36).substring(2)}`}
|
||||
className="relative group cursor-default user-select-none rounded-xl p-2 bg-transparent"
|
||||
>
|
||||
<div className="animate-pulse">
|
||||
<div className="w-full aspect-[2/3] bg-mediaCard-hoverBackground rounded-lg" />
|
||||
<div className="mt-2 h-4 bg-mediaCard-hoverBackground rounded w-3/4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
))}
|
||||
</MediaGrid>
|
||||
</div>
|
||||
</WideContainer>
|
||||
|
|
|
|||
|
|
@ -213,6 +213,7 @@ export function MediaCarousel({
|
|||
genreName: selectedGenreName,
|
||||
providerName: selectedProviderName,
|
||||
mediaTitle: selectedRecommendationTitle,
|
||||
isCarouselView: true,
|
||||
});
|
||||
|
||||
// Find active button
|
||||
|
|
@ -313,11 +314,13 @@ export function MediaCarousel({
|
|||
<div className="relative overflow-hidden carousel-container md:pb-4">
|
||||
<div className="grid grid-flow-col auto-cols-max gap-4 pt-0 overflow-x-scroll scrollbar-none rounded-xl overflow-y-hidden md:pl-8 md:pr-8">
|
||||
<div className="md:w-12" />
|
||||
{Array.from({ length: 10 }).map(() => (
|
||||
<MediaCardSkeleton
|
||||
key={`loading-skeleton-${Math.random().toString(36).substring(7)}`}
|
||||
/>
|
||||
))}
|
||||
{Array(10)
|
||||
.fill(null)
|
||||
.map(() => (
|
||||
<MediaCardSkeleton
|
||||
key={`skeleton-loading-${Math.random().toString(36).substring(2)}`}
|
||||
/>
|
||||
))}
|
||||
<div className="md:w-12" />
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -533,11 +536,13 @@ export function MediaCarousel({
|
|||
/>
|
||||
</div>
|
||||
))
|
||||
: Array.from({ length: 10 }).map(() => (
|
||||
<MediaCardSkeleton
|
||||
key={`loading-skeleton-${Math.random().toString(36).substring(7)}`}
|
||||
/>
|
||||
))}
|
||||
: Array(10)
|
||||
.fill(null)
|
||||
.map((_, i) => (
|
||||
<MediaCardSkeleton
|
||||
key={`skeleton-${categorySlug}-${Math.random().toString(36).substring(2)}`}
|
||||
/>
|
||||
))}
|
||||
|
||||
{moreContent && generatedMoreLink && (
|
||||
<MoreCard link={generatedMoreLink} />
|
||||
|
|
|
|||
|
|
@ -129,6 +129,8 @@ export interface UseDiscoverMediaProps {
|
|||
providerName?: string;
|
||||
/** Media title for recommendations display */
|
||||
mediaTitle?: string;
|
||||
/** Whether this is for a carousel view (limits results) */
|
||||
isCarouselView?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -284,6 +286,7 @@ export function useDiscoverMedia({
|
|||
genreName,
|
||||
providerName,
|
||||
mediaTitle,
|
||||
isCarouselView = false,
|
||||
}: UseDiscoverMediaProps): UseDiscoverMediaReturn {
|
||||
const [media, setMedia] = useState<DiscoverMedia[]>([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
|
|
@ -308,15 +311,26 @@ export function useDiscoverMedia({
|
|||
const fetchTMDBMedia = useCallback(
|
||||
async (endpoint: string, params: Record<string, any> = {}) => {
|
||||
try {
|
||||
// For carousel views, we only need one page of results
|
||||
if (isCarouselView) {
|
||||
params.page = "1"; // Always use first page for carousels
|
||||
} else {
|
||||
params.page = page.toString(); // Use the requested page for "view more" pages
|
||||
}
|
||||
|
||||
const data = await get<any>(endpoint, {
|
||||
api_key: conf().TMDB_READ_API_KEY,
|
||||
language: formattedLanguage,
|
||||
page: page.toString(),
|
||||
...params,
|
||||
});
|
||||
|
||||
// For carousel views, we might want to limit the number of results
|
||||
const results = isCarouselView
|
||||
? data.results.slice(0, 20)
|
||||
: data.results;
|
||||
|
||||
return {
|
||||
results: data.results.map((item: any) => ({
|
||||
results: results.map((item: any) => ({
|
||||
...item,
|
||||
type: mediaType === "movie" ? "movie" : "show",
|
||||
})),
|
||||
|
|
@ -327,7 +341,7 @@ export function useDiscoverMedia({
|
|||
throw err;
|
||||
}
|
||||
},
|
||||
[formattedLanguage, page, mediaType],
|
||||
[formattedLanguage, page, mediaType, isCarouselView],
|
||||
);
|
||||
|
||||
const fetchTraktMedia = useCallback(
|
||||
|
|
@ -342,13 +356,18 @@ export function useDiscoverMedia({
|
|||
const response = await Promise.race([traktFunction(), timeoutPromise]);
|
||||
|
||||
// Paginate the results
|
||||
const pageSize = isCarouselView ? 20 : 100; // Limit to 20 items for carousels, get more for detailed views
|
||||
const { tmdb_ids: tmdbIds, hasMore: hasMoreResults } = paginateResults(
|
||||
response,
|
||||
page,
|
||||
pageSize,
|
||||
);
|
||||
|
||||
// For carousel views, we only need to fetch details for displayed items
|
||||
const idsToFetch = isCarouselView ? tmdbIds.slice(0, 20) : tmdbIds;
|
||||
|
||||
// Fetch details for each TMDB ID
|
||||
const mediaPromises = tmdbIds.map(async (tmdbId: number) => {
|
||||
const mediaPromises = idsToFetch.map(async (tmdbId: number) => {
|
||||
const endpoint = `/${mediaType}/${tmdbId}`;
|
||||
try {
|
||||
const data = await get<any>(endpoint, {
|
||||
|
|
@ -385,7 +404,7 @@ export function useDiscoverMedia({
|
|||
throw err;
|
||||
}
|
||||
},
|
||||
[mediaType, formattedLanguage, page],
|
||||
[mediaType, formattedLanguage, page, isCarouselView],
|
||||
);
|
||||
|
||||
// Get Trakt function for provider
|
||||
|
|
@ -442,8 +461,11 @@ export function useDiscoverMedia({
|
|||
const picks =
|
||||
mediaType === "movie" ? EDITOR_PICKS_MOVIES : EDITOR_PICKS_TV_SHOWS;
|
||||
|
||||
// For carousel views, limit the number of picks to fetch
|
||||
const picksToFetch = isCarouselView ? picks.slice(0, 20) : picks;
|
||||
|
||||
try {
|
||||
const mediaPromises = picks.map(async (item) => {
|
||||
const mediaPromises = picksToFetch.map(async (item) => {
|
||||
const endpoint = `/${mediaType}/${item.id}`;
|
||||
const data = await get<any>(endpoint, {
|
||||
api_key: conf().TMDB_READ_API_KEY,
|
||||
|
|
@ -459,13 +481,13 @@ export function useDiscoverMedia({
|
|||
const results = await Promise.all(mediaPromises);
|
||||
return {
|
||||
results,
|
||||
hasMore: false,
|
||||
hasMore: picks.length > picksToFetch.length,
|
||||
};
|
||||
} catch (err) {
|
||||
console.error("Error fetching editor picks:", err);
|
||||
throw err;
|
||||
}
|
||||
}, [mediaType, formattedLanguage]);
|
||||
}, [mediaType, formattedLanguage, isCarouselView]);
|
||||
|
||||
const fetchMedia = useCallback(async () => {
|
||||
setIsLoading(true);
|
||||
|
|
|
|||
Loading…
Reference in a new issue