mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +00:00
Added collections ection
This commit is contained in:
parent
f90752bdb7
commit
a7fbd567fd
5 changed files with 410 additions and 0 deletions
234
src/components/metadata/CollectionSection.tsx
Normal file
234
src/components/metadata/CollectionSection.tsx
Normal file
|
|
@ -0,0 +1,234 @@
|
||||||
|
import React from 'react';
|
||||||
|
import {
|
||||||
|
View,
|
||||||
|
Text,
|
||||||
|
StyleSheet,
|
||||||
|
FlatList,
|
||||||
|
TouchableOpacity,
|
||||||
|
ActivityIndicator,
|
||||||
|
Dimensions,
|
||||||
|
} from 'react-native';
|
||||||
|
import FastImage from '@d11/react-native-fast-image';
|
||||||
|
import { useNavigation, StackActions } from '@react-navigation/native';
|
||||||
|
import { NavigationProp } from '@react-navigation/native';
|
||||||
|
import { RootStackParamList } from '../../navigation/AppNavigator';
|
||||||
|
import { StreamingContent } from '../../services/catalogService';
|
||||||
|
import { useTheme } from '../../contexts/ThemeContext';
|
||||||
|
import { TMDBService } from '../../services/tmdbService';
|
||||||
|
import { catalogService } from '../../services/catalogService';
|
||||||
|
import CustomAlert from '../../components/CustomAlert';
|
||||||
|
|
||||||
|
const { width } = Dimensions.get('window');
|
||||||
|
|
||||||
|
// Breakpoints for responsive sizing
|
||||||
|
const BREAKPOINTS = {
|
||||||
|
phone: 0,
|
||||||
|
tablet: 768,
|
||||||
|
largeTablet: 1024,
|
||||||
|
tv: 1440,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
interface CollectionSectionProps {
|
||||||
|
collectionName: string;
|
||||||
|
collectionMovies: StreamingContent[];
|
||||||
|
loadingCollection: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CollectionSection: React.FC<CollectionSectionProps> = ({
|
||||||
|
collectionName,
|
||||||
|
collectionMovies,
|
||||||
|
loadingCollection
|
||||||
|
}) => {
|
||||||
|
const { currentTheme } = useTheme();
|
||||||
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
|
|
||||||
|
// Determine device type
|
||||||
|
const deviceWidth = Dimensions.get('window').width;
|
||||||
|
const getDeviceType = React.useCallback(() => {
|
||||||
|
if (deviceWidth >= BREAKPOINTS.tv) return 'tv';
|
||||||
|
if (deviceWidth >= BREAKPOINTS.largeTablet) return 'largeTablet';
|
||||||
|
if (deviceWidth >= BREAKPOINTS.tablet) return 'tablet';
|
||||||
|
return 'phone';
|
||||||
|
}, [deviceWidth]);
|
||||||
|
const deviceType = getDeviceType();
|
||||||
|
const isTablet = deviceType === 'tablet';
|
||||||
|
const isLargeTablet = deviceType === 'largeTablet';
|
||||||
|
const isTV = deviceType === 'tv';
|
||||||
|
|
||||||
|
// Responsive spacing & sizes
|
||||||
|
const horizontalPadding = React.useMemo(() => {
|
||||||
|
switch (deviceType) {
|
||||||
|
case 'tv': return 32;
|
||||||
|
case 'largeTablet': return 28;
|
||||||
|
case 'tablet': return 24;
|
||||||
|
default: return 16;
|
||||||
|
}
|
||||||
|
}, [deviceType]);
|
||||||
|
|
||||||
|
const itemSpacing = React.useMemo(() => {
|
||||||
|
switch (deviceType) {
|
||||||
|
case 'tv': return 14;
|
||||||
|
case 'largeTablet': return 12;
|
||||||
|
case 'tablet': return 12;
|
||||||
|
default: return 12;
|
||||||
|
}
|
||||||
|
}, [deviceType]);
|
||||||
|
|
||||||
|
const backdropWidth = React.useMemo(() => {
|
||||||
|
switch (deviceType) {
|
||||||
|
case 'tv': return 240;
|
||||||
|
case 'largeTablet': return 220;
|
||||||
|
case 'tablet': return 200;
|
||||||
|
default: return 180;
|
||||||
|
}
|
||||||
|
}, [deviceType]);
|
||||||
|
const backdropHeight = React.useMemo(() => backdropWidth * (9/16), [backdropWidth]); // 16:9 aspect ratio
|
||||||
|
|
||||||
|
const [alertVisible, setAlertVisible] = React.useState(false);
|
||||||
|
const [alertTitle, setAlertTitle] = React.useState('');
|
||||||
|
const [alertMessage, setAlertMessage] = React.useState('');
|
||||||
|
const [alertActions, setAlertActions] = React.useState<any[]>([]);
|
||||||
|
|
||||||
|
const handleItemPress = async (item: StreamingContent) => {
|
||||||
|
try {
|
||||||
|
// Extract TMDB ID from the tmdb:123456 format
|
||||||
|
const tmdbId = item.id.replace('tmdb:', '');
|
||||||
|
|
||||||
|
// Get Stremio ID directly using catalogService
|
||||||
|
const stremioId = await catalogService.getStremioId(item.type, tmdbId);
|
||||||
|
|
||||||
|
if (stremioId) {
|
||||||
|
navigation.dispatch(
|
||||||
|
StackActions.push('Metadata', {
|
||||||
|
id: stremioId,
|
||||||
|
type: item.type
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
throw new Error('Could not find Stremio ID');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (__DEV__) console.error('Error navigating to collection item:', error);
|
||||||
|
setAlertTitle('Error');
|
||||||
|
setAlertMessage('Unable to load this content. Please try again later.');
|
||||||
|
setAlertActions([{ label: 'OK', onPress: () => {} }]);
|
||||||
|
setAlertVisible(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderItem = ({ item }: { item: StreamingContent }) => (
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.itemContainer, { width: backdropWidth, marginRight: itemSpacing }]}
|
||||||
|
onPress={() => handleItemPress(item)}
|
||||||
|
>
|
||||||
|
<FastImage
|
||||||
|
source={{ uri: item.banner || item.poster }}
|
||||||
|
style={[styles.backdrop, {
|
||||||
|
backgroundColor: currentTheme.colors.elevation1,
|
||||||
|
width: backdropWidth,
|
||||||
|
height: backdropHeight,
|
||||||
|
borderRadius: isTV ? 12 : isLargeTablet ? 10 : isTablet ? 10 : 8
|
||||||
|
}]}
|
||||||
|
resizeMode={FastImage.resizeMode.cover}
|
||||||
|
/>
|
||||||
|
<Text style={[styles.title, {
|
||||||
|
color: currentTheme.colors.mediumEmphasis,
|
||||||
|
fontSize: isTV ? 14 : isLargeTablet ? 13 : isTablet ? 13 : 13,
|
||||||
|
lineHeight: isTV ? 20 : 18
|
||||||
|
}]} numberOfLines={2}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
{item.year && (
|
||||||
|
<Text style={[styles.year, {
|
||||||
|
color: currentTheme.colors.textMuted,
|
||||||
|
fontSize: isTV ? 12 : isLargeTablet ? 11 : isTablet ? 11 : 11
|
||||||
|
}]}>
|
||||||
|
{item.year}
|
||||||
|
</Text>
|
||||||
|
)}
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
|
|
||||||
|
if (loadingCollection) {
|
||||||
|
return (
|
||||||
|
<View style={styles.loadingContainer}>
|
||||||
|
<ActivityIndicator size="small" color={currentTheme.colors.primary} />
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collectionMovies || collectionMovies.length === 0) {
|
||||||
|
return null; // Don't render anything if there are no collection movies
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View style={[styles.container, { paddingLeft: 0 }] }>
|
||||||
|
<Text style={[styles.sectionTitle, {
|
||||||
|
color: currentTheme.colors.highEmphasis,
|
||||||
|
fontSize: isTV ? 24 : isLargeTablet ? 22 : isTablet ? 20 : 20,
|
||||||
|
paddingHorizontal: horizontalPadding
|
||||||
|
}]}>
|
||||||
|
{collectionName}
|
||||||
|
</Text>
|
||||||
|
<FlatList
|
||||||
|
data={collectionMovies}
|
||||||
|
renderItem={renderItem}
|
||||||
|
keyExtractor={(item) => item.id}
|
||||||
|
horizontal
|
||||||
|
showsHorizontalScrollIndicator={false}
|
||||||
|
contentContainerStyle={[styles.listContentContainer, {
|
||||||
|
paddingHorizontal: horizontalPadding,
|
||||||
|
paddingRight: horizontalPadding + itemSpacing
|
||||||
|
}]}
|
||||||
|
/>
|
||||||
|
<CustomAlert
|
||||||
|
visible={alertVisible}
|
||||||
|
title={alertTitle}
|
||||||
|
message={alertMessage}
|
||||||
|
actions={alertActions}
|
||||||
|
onClose={() => setAlertVisible(false)}
|
||||||
|
/>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const styles = StyleSheet.create({
|
||||||
|
container: {
|
||||||
|
marginTop: 16,
|
||||||
|
marginBottom: 16,
|
||||||
|
},
|
||||||
|
sectionTitle: {
|
||||||
|
fontSize: 20,
|
||||||
|
fontWeight: '800',
|
||||||
|
marginBottom: 12,
|
||||||
|
marginTop: 8,
|
||||||
|
},
|
||||||
|
listContentContainer: {
|
||||||
|
paddingRight: 32, // Will be overridden responsively
|
||||||
|
},
|
||||||
|
itemContainer: {
|
||||||
|
marginRight: 12, // will be overridden responsively
|
||||||
|
},
|
||||||
|
backdrop: {
|
||||||
|
borderRadius: 8, // overridden responsively
|
||||||
|
marginBottom: 8,
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
fontSize: 13, // overridden responsively
|
||||||
|
fontWeight: '500',
|
||||||
|
lineHeight: 18, // overridden responsively
|
||||||
|
marginBottom: 2,
|
||||||
|
},
|
||||||
|
year: {
|
||||||
|
fontSize: 11, // overridden responsively
|
||||||
|
fontWeight: '400',
|
||||||
|
opacity: 0.8,
|
||||||
|
},
|
||||||
|
loadingContainer: {
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
paddingVertical: 20,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export default CollectionSection;
|
||||||
|
|
@ -107,6 +107,8 @@ interface UseMetadataReturn {
|
||||||
imdbId: string | null;
|
imdbId: string | null;
|
||||||
scraperStatuses: ScraperStatus[];
|
scraperStatuses: ScraperStatus[];
|
||||||
activeFetchingScrapers: string[];
|
activeFetchingScrapers: string[];
|
||||||
|
collectionMovies: StreamingContent[];
|
||||||
|
loadingCollection: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadataReturn => {
|
export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadataReturn => {
|
||||||
|
|
@ -132,6 +134,8 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
const [loadAttempts, setLoadAttempts] = useState(0);
|
const [loadAttempts, setLoadAttempts] = useState(0);
|
||||||
const [recommendations, setRecommendations] = useState<StreamingContent[]>([]);
|
const [recommendations, setRecommendations] = useState<StreamingContent[]>([]);
|
||||||
const [loadingRecommendations, setLoadingRecommendations] = useState(false);
|
const [loadingRecommendations, setLoadingRecommendations] = useState(false);
|
||||||
|
const [collectionMovies, setCollectionMovies] = useState<StreamingContent[]>([]);
|
||||||
|
const [loadingCollection, setLoadingCollection] = useState(false);
|
||||||
const [imdbId, setImdbId] = useState<string | null>(null);
|
const [imdbId, setImdbId] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [availableStreams, setAvailableStreams] = useState<{ [sourceType: string]: Stream }>({});
|
const [availableStreams, setAvailableStreams] = useState<{ [sourceType: string]: Stream }>({});
|
||||||
|
|
@ -1939,6 +1943,94 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
tmdbId,
|
tmdbId,
|
||||||
movieDetails: movieDetailsObj
|
movieDetails: movieDetailsObj
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
// Fetch collection data if movie belongs to a collection
|
||||||
|
if (movieDetails.belongs_to_collection) {
|
||||||
|
setLoadingCollection(true);
|
||||||
|
try {
|
||||||
|
const collectionDetails = await tmdbService.getCollectionDetails(
|
||||||
|
movieDetails.belongs_to_collection.id,
|
||||||
|
lang
|
||||||
|
);
|
||||||
|
|
||||||
|
if (collectionDetails && collectionDetails.parts) {
|
||||||
|
// Fetch individual movie images to get backdrops with embedded titles/logos
|
||||||
|
const collectionMoviesData = await Promise.all(
|
||||||
|
collectionDetails.parts.map(async (part: any, index: number) => {
|
||||||
|
let movieBackdropUrl = undefined;
|
||||||
|
|
||||||
|
// Try to fetch movie images with language parameter
|
||||||
|
try {
|
||||||
|
const movieImages = await tmdbService.getMovieImagesFull(part.id);
|
||||||
|
if (movieImages && movieImages.backdrops && movieImages.backdrops.length > 0) {
|
||||||
|
// Filter and sort backdrops by language and quality
|
||||||
|
const languageBackdrops = movieImages.backdrops
|
||||||
|
.filter((backdrop: any) => backdrop.aspect_ratio > 1.0) // Landscape orientation
|
||||||
|
.sort((a: any, b: any) => {
|
||||||
|
// Prioritize backdrops with the requested language
|
||||||
|
const aHasLang = a.iso_639_1 === lang;
|
||||||
|
const bHasLang = b.iso_639_1 === lang;
|
||||||
|
if (aHasLang && !bHasLang) return -1;
|
||||||
|
if (!aHasLang && bHasLang) return 1;
|
||||||
|
|
||||||
|
// Then prioritize English if requested language not available
|
||||||
|
const aIsEn = a.iso_639_1 === 'en';
|
||||||
|
const bIsEn = b.iso_639_1 === 'en';
|
||||||
|
if (aIsEn && !bIsEn) return -1;
|
||||||
|
if (!aIsEn && bIsEn) return 1;
|
||||||
|
|
||||||
|
// Then sort by vote average (quality), then by resolution
|
||||||
|
if (a.vote_average !== b.vote_average) {
|
||||||
|
return b.vote_average - a.vote_average;
|
||||||
|
}
|
||||||
|
return (b.width * b.height) - (a.width * a.height);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (languageBackdrops.length > 0) {
|
||||||
|
movieBackdropUrl = tmdbService.getImageUrl(languageBackdrops[0].file_path, 'original');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (__DEV__) console.warn('[useMetadata] Failed to fetch movie images for:', part.id, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: `tmdb:${part.id}`,
|
||||||
|
type: 'movie',
|
||||||
|
name: part.title,
|
||||||
|
poster: part.poster_path ? tmdbService.getImageUrl(part.poster_path, 'w500') : 'https://via.placeholder.com/300x450/cccccc/666666?text=No+Image',
|
||||||
|
banner: movieBackdropUrl || (part.backdrop_path ? tmdbService.getImageUrl(part.backdrop_path, 'original') : undefined),
|
||||||
|
year: part.release_date ? new Date(part.release_date).getFullYear() : undefined,
|
||||||
|
description: part.overview,
|
||||||
|
collection: {
|
||||||
|
id: collectionDetails.id,
|
||||||
|
name: collectionDetails.name,
|
||||||
|
poster_path: collectionDetails.poster_path,
|
||||||
|
backdrop_path: collectionDetails.backdrop_path
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
) as StreamingContent[];
|
||||||
|
|
||||||
|
setCollectionMovies(collectionMoviesData);
|
||||||
|
|
||||||
|
// Update metadata with collection info
|
||||||
|
setMetadata((prev: any) => ({
|
||||||
|
...prev,
|
||||||
|
collection: {
|
||||||
|
id: collectionDetails.id,
|
||||||
|
name: collectionDetails.name,
|
||||||
|
poster_path: collectionDetails.poster_path,
|
||||||
|
backdrop_path: collectionDetails.backdrop_path
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (__DEV__) console.error('[useMetadata] Error fetching collection:', error);
|
||||||
|
} finally {
|
||||||
|
setLoadingCollection(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2024,5 +2116,7 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
|
||||||
imdbId,
|
imdbId,
|
||||||
scraperStatuses,
|
scraperStatuses,
|
||||||
activeFetchingScrapers,
|
activeFetchingScrapers,
|
||||||
|
collectionMovies,
|
||||||
|
loadingCollection,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
@ -28,6 +28,7 @@ import { MoreLikeThisSection } from '../components/metadata/MoreLikeThisSection'
|
||||||
import { RatingsSection } from '../components/metadata/RatingsSection';
|
import { RatingsSection } from '../components/metadata/RatingsSection';
|
||||||
import { CommentsSection, CommentBottomSheet } from '../components/metadata/CommentsSection';
|
import { CommentsSection, CommentBottomSheet } from '../components/metadata/CommentsSection';
|
||||||
import TrailersSection from '../components/metadata/TrailersSection';
|
import TrailersSection from '../components/metadata/TrailersSection';
|
||||||
|
import CollectionSection from '../components/metadata/CollectionSection';
|
||||||
import { RouteParams, Episode } from '../types/metadata';
|
import { RouteParams, Episode } from '../types/metadata';
|
||||||
import Animated, {
|
import Animated, {
|
||||||
useAnimatedStyle,
|
useAnimatedStyle,
|
||||||
|
|
@ -182,6 +183,8 @@ const MetadataScreen: React.FC = () => {
|
||||||
setMetadata,
|
setMetadata,
|
||||||
imdbId,
|
imdbId,
|
||||||
tmdbId,
|
tmdbId,
|
||||||
|
collectionMovies,
|
||||||
|
loadingCollection,
|
||||||
} = useMetadata({ id, type, addonId });
|
} = useMetadata({ id, type, addonId });
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1245,6 +1248,18 @@ const MetadataScreen: React.FC = () => {
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{/* Collection Section - Lazy loaded */}
|
||||||
|
{shouldLoadSecondaryData &&
|
||||||
|
Object.keys(groupedEpisodes).length === 0 &&
|
||||||
|
metadata?.collection &&
|
||||||
|
settings.enrichMetadataWithTMDB && (
|
||||||
|
<CollectionSection
|
||||||
|
collectionName={metadata.collection.name}
|
||||||
|
collectionMovies={collectionMovies}
|
||||||
|
loadingCollection={loadingCollection}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Recommendations Section with skeleton when loading - Lazy loaded */}
|
{/* Recommendations Section with skeleton when loading - Lazy loaded */}
|
||||||
{type === 'movie' && shouldLoadSecondaryData && (
|
{type === 'movie' && shouldLoadSecondaryData && (
|
||||||
<MemoizedMoreLikeThisSection
|
<MemoizedMoreLikeThisSection
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,12 @@ export interface StreamingContent {
|
||||||
originCountry?: string[];
|
originCountry?: string[];
|
||||||
tagline?: string;
|
tagline?: string;
|
||||||
};
|
};
|
||||||
|
collection?: {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
poster_path?: string;
|
||||||
|
backdrop_path?: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface CatalogContent {
|
export interface CatalogContent {
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,32 @@ export interface TMDBTrendingResult {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface TMDBCollection {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
overview: string;
|
||||||
|
poster_path: string | null;
|
||||||
|
backdrop_path: string | null;
|
||||||
|
parts: TMDBCollectionPart[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TMDBCollectionPart {
|
||||||
|
id: number;
|
||||||
|
title: string;
|
||||||
|
overview: string;
|
||||||
|
poster_path: string | null;
|
||||||
|
backdrop_path: string | null;
|
||||||
|
release_date: string;
|
||||||
|
adult: boolean;
|
||||||
|
video: boolean;
|
||||||
|
vote_average: number;
|
||||||
|
vote_count: number;
|
||||||
|
genre_ids: number[];
|
||||||
|
original_language: string;
|
||||||
|
original_title: string;
|
||||||
|
popularity: number;
|
||||||
|
}
|
||||||
|
|
||||||
export class TMDBService {
|
export class TMDBService {
|
||||||
private static instance: TMDBService;
|
private static instance: TMDBService;
|
||||||
private static ratingCache: Map<string, number | null> = new Map();
|
private static ratingCache: Map<string, number | null> = new Map();
|
||||||
|
|
@ -604,6 +630,41 @@ export class TMDBService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get collection details by collection ID
|
||||||
|
*/
|
||||||
|
async getCollectionDetails(collectionId: number, language: string = 'en'): Promise<TMDBCollection | null> {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${BASE_URL}/collection/${collectionId}`, {
|
||||||
|
headers: await this.getHeaders(),
|
||||||
|
params: await this.getParams({
|
||||||
|
language,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get collection images by collection ID
|
||||||
|
*/
|
||||||
|
async getCollectionImages(collectionId: number, language: string = 'en'): Promise<any> {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(`${BASE_URL}/collection/${collectionId}/images`, {
|
||||||
|
headers: await this.getHeaders(),
|
||||||
|
params: await this.getParams({
|
||||||
|
language,
|
||||||
|
include_image_language: `${language},en,null`
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get movie images (logos, posters, backdrops) by TMDB ID - returns full images object
|
* Get movie images (logos, posters, backdrops) by TMDB ID - returns full images object
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue