network logic

This commit is contained in:
tapframe 2025-10-13 13:16:38 +05:30
parent 544dc8b639
commit a0d9420be2
5 changed files with 157 additions and 4 deletions

View file

@ -1534,6 +1534,7 @@ const HeroSection: React.FC<HeroSectionProps> = memo(({
</Animated.View>
)}
{/* Optimized Action Buttons */}
<ActionButtons
handleShowStreams={handleShowStreams}

View file

@ -1766,6 +1766,62 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
maybeAttachCertification();
}, [tmdbId, metadata, type, settings.enrichMetadataWithTMDB]);
// Fetch TMDB networks/production companies when TMDB ID is available and enrichment is enabled
const productionInfoFetchedRef = useRef<string | null>(null);
useEffect(() => {
if (!tmdbId || !settings.enrichMetadataWithTMDB || !metadata) return;
const contentKey = `${type}-${tmdbId}`;
if (productionInfoFetchedRef.current === contentKey || (metadata as any).networks) return;
const fetchProductionInfo = async () => {
try {
productionInfoFetchedRef.current = contentKey;
const tmdbService = TMDBService.getInstance();
let productionInfo: any[] = [];
if (type === 'series') {
// Fetch networks for TV shows
const showDetails = await tmdbService.getTVShowDetails(tmdbId, 'en-US');
if (showDetails && showDetails.networks) {
productionInfo = Array.isArray(showDetails.networks)
? showDetails.networks
.map((n: any) => ({
id: n?.id,
name: n?.name,
logo: tmdbService.getImageUrl(n?.logo_path, 'w185'),
}))
.filter((n: any) => n && (n.logo || n.name))
: [];
}
} else if (type === 'movie') {
// Fetch production companies for movies
const movieDetails = await tmdbService.getMovieDetails(String(tmdbId), 'en-US');
if (movieDetails && movieDetails.production_companies) {
productionInfo = Array.isArray(movieDetails.production_companies)
? movieDetails.production_companies
.map((c: any) => ({
id: c?.id,
name: c?.name,
logo: tmdbService.getImageUrl(c?.logo_path, 'w185'),
}))
.filter((c: any) => c && (c.logo || c.name))
: [];
}
}
if (__DEV__) console.log('[useMetadata] Fetched production info via TMDB:', productionInfo);
if (productionInfo.length > 0) {
setMetadata((prev: any) => ({ ...prev, networks: productionInfo }));
}
} catch (error) {
if (__DEV__) console.error('[useMetadata] Failed to fetch production info:', error);
}
};
fetchProductionInfo();
}, [tmdbId, settings.enrichMetadataWithTMDB, metadata, type]);
// Reset tmdbId when id changes
useEffect(() => {
setTmdbId(null);
@ -1791,7 +1847,10 @@ export const useMetadata = ({ id, type, addonId }: UseMetadataProps): UseMetadat
// Force cleanup
cleanupStreams();
// Reset production info fetch tracking
productionInfoFetchedRef.current = null;
if (__DEV__) console.log('[useMetadata] Component unmounted, memory cleaned up');
};
}, [cleanupStreams]);

View file

@ -45,6 +45,7 @@ import { RootStackParamList } from '../navigation/AppNavigator';
import { useSettings } from '../hooks/useSettings';
import { MetadataLoadingScreen } from '../components/loading/MetadataLoadingScreen';
import { useTrailer } from '../contexts/TrailerContext';
import FastImage from '@d11/react-native-fast-image';
// Import our optimized components and hooks
import HeroSection from '../components/metadata/HeroSection';
@ -141,7 +142,9 @@ const MetadataScreen: React.FC = () => {
hasEpisodes: episodes.length > 0,
seasonsCount: Object.keys(groupedEpisodes).length,
imdbId,
tmdbId
tmdbId,
hasNetworks: !!(metadata as any)?.networks,
networksCount: metadata?.networks ? metadata.networks.length : 0
});
}, [loading, metadata, metadataError, cast.length, episodes.length, Object.keys(groupedEpisodes).length, imdbId, tmdbId]);
@ -852,6 +855,28 @@ const MetadataScreen: React.FC = () => {
) : null}
/>
{/* Production info row — shown below description and above cast for series */}
{shouldLoadSecondaryData && Object.keys(groupedEpisodes).length > 0 && metadata?.networks && metadata.networks.length > 0 && (
<View style={styles.productionContainer}>
<Text style={styles.productionHeader}>Network</Text>
<View style={styles.productionRow}>
{metadata.networks.slice(0, 6).map((net) => (
<View key={String(net.id || net.name)} style={styles.productionChip}>
{net.logo ? (
<FastImage
source={{ uri: net.logo }}
style={styles.productionLogo}
resizeMode={FastImage.resizeMode.contain}
/>
) : (
<Text style={styles.productionText}>{net.name}</Text>
)}
</View>
))}
</View>
</View>
)}
{/* Cast Section with skeleton when loading - Lazy loaded */}
{shouldLoadSecondaryData && (
<MemoizedCastSection
@ -862,6 +887,28 @@ const MetadataScreen: React.FC = () => {
/>
)}
{/* Production info row — shown after cast for movies */}
{shouldLoadSecondaryData && Object.keys(groupedEpisodes).length === 0 && metadata?.networks && metadata.networks.length > 0 && (
<View style={styles.productionContainer}>
<Text style={styles.productionHeader}>Production</Text>
<View style={styles.productionRow}>
{metadata.networks.slice(0, 6).map((net) => (
<View key={String(net.id || net.name)} style={styles.productionChip}>
{net.logo ? (
<FastImage
source={{ uri: net.logo }}
style={styles.productionLogo}
resizeMode={FastImage.resizeMode.contain}
/>
) : (
<Text style={styles.productionText}>{net.name}</Text>
)}
</View>
))}
</View>
</View>
)}
{/* Comments Section - Lazy loaded */}
{shouldLoadSecondaryData && imdbId && (
<MemoizedCommentsSection
@ -1034,6 +1081,47 @@ const styles = StyleSheet.create({
borderRadius: 8,
marginBottom: 8,
},
productionContainer: {
paddingHorizontal: 16,
marginTop: 0,
marginBottom: 20,
},
productionRow: {
flexDirection: 'row',
flexWrap: 'wrap',
alignItems: 'center',
gap: 8,
},
productionChip: {
paddingVertical: 8,
paddingHorizontal: 12,
backgroundColor: 'rgba(245,245,245,0.9)',
borderRadius: 12,
borderWidth: 1,
borderColor: 'rgba(255,255,255,0.15)',
alignItems: 'center',
justifyContent: 'center',
minHeight: 36,
},
productionLogo: {
width: 64,
height: 22,
},
productionText: {
color: '#333',
fontSize: 12,
fontWeight: '600',
opacity: 0.9,
},
productionHeader: {
fontSize: 14,
fontWeight: '700',
color: '#fff',
marginBottom: 8,
textTransform: 'uppercase',
letterSpacing: 1,
opacity: 0.8,
},
});

View file

@ -93,6 +93,11 @@ export interface StreamingContent {
character: string;
profile_path: string | null;
}>;
networks?: Array<{
id: number | string;
name: string;
logo?: string;
}>;
}
export interface CatalogContent {

View file

@ -166,7 +166,7 @@ export class TMDBService {
headers: await this.getHeaders(),
params: await this.getParams({
language,
append_to_response: 'external_ids,credits,keywords' // Append external IDs, cast/crew, and keywords for AI context
append_to_response: 'external_ids,credits,keywords,networks' // Append external IDs, cast/crew, keywords, and networks
}),
});
return response.data;
@ -588,7 +588,7 @@ export class TMDBService {
headers: await this.getHeaders(),
params: await this.getParams({
language,
append_to_response: 'external_ids,credits,keywords,release_dates' // Include release dates for accurate availability
append_to_response: 'external_ids,credits,keywords,release_dates,production_companies' // Include release dates and production companies
}),
});
return response.data;