diff --git a/frontend/src/pages/VODs.jsx b/frontend/src/pages/VODs.jsx index d391b887..8a4b4ab7 100644 --- a/frontend/src/pages/VODs.jsx +++ b/frontend/src/pages/VODs.jsx @@ -282,6 +282,8 @@ const SeriesModal = ({ series, opened, onClose }) => { const VODModal = ({ vod, opened, onClose }) => { const [detailedVOD, setDetailedVOD] = useState(null); const [loadingDetails, setLoadingDetails] = useState(false); + const [trailerModalOpened, setTrailerModalOpened] = useState(false); + const [trailerUrl, setTrailerUrl] = useState(''); const { fetchVODDetailsFromProvider } = useVODStore(); const showVideo = useVideoStore((s) => s.showVideo); const env_mode = useSettingsStore((s) => s.environment.env_mode); @@ -307,6 +309,8 @@ const VODModal = ({ vod, opened, onClose }) => { if (!opened) { setDetailedVOD(null); setLoadingDetails(false); + setTrailerModalOpened(false); + setTrailerUrl(''); } }, [opened]); @@ -330,265 +334,305 @@ const VODModal = ({ vod, opened, onClose }) => { return hours > 0 ? `${hours}h ${mins}m` : `${mins}m`; }; + // Helper to get embeddable YouTube URL + const getEmbedUrl = (url) => { + if (!url) return ''; + // Accepts full YouTube URLs or just IDs + const match = url.match(/(?:youtube\.com\/watch\?v=|youtu\.be\/)([\w-]+)/); + const videoId = match ? match[1] : url; + return `https://www.youtube.com/embed/${videoId}`; + }; + if (!vod) return null; // Use detailed data if available, otherwise use basic vod data const displayVOD = detailedVOD || vod; return ( - - - {/* Backdrop image as background */} - {displayVOD.backdrop_path && displayVOD.backdrop_path.length > 0 && ( - <> - {`${displayVOD.name} + + + {/* Backdrop image as background */} + {displayVOD.backdrop_path && displayVOD.backdrop_path.length > 0 && ( + <> + {`${displayVOD.name} + {/* Overlay for readability */} + + + )} + {/* Modal content above backdrop */} + + + {loadingDetails && ( + + + Loading additional details... + + )} + + {/* Movie poster and basic info */} + + {/* Use movie_image or logo */} + {(displayVOD.movie_image || displayVOD.logo?.url) ? ( + + {displayVOD.name} + + ) : ( + + + + )} + + + {displayVOD.name} + + {/* Original name if different */} + {displayVOD.o_name && displayVOD.o_name !== displayVOD.name && ( + + Original: {displayVOD.o_name} + + )} + + + {displayVOD.year && {displayVOD.year}} + {displayVOD.duration && {formatDuration(displayVOD.duration)}} + {displayVOD.rating && {displayVOD.rating}} + {displayVOD.age && {displayVOD.age}} + Movie + + + {/* Release date */} + {displayVOD.release_date && ( + + Release Date: {displayVOD.release_date} + + )} + + {displayVOD.genre && ( + + Genre: {displayVOD.genre} + + )} + + {displayVOD.director && ( + + Director: {displayVOD.director} + + )} + + {displayVOD.actors && ( + + Cast: {displayVOD.actors} + + )} + + {displayVOD.country && ( + + Country: {displayVOD.country} + + )} + + {/* Description */} + {displayVOD.description && ( + + Description + + {displayVOD.description} + + + )} + + {/* Watch Trailer button at top */} + {displayVOD.youtube_trailer && ( + + )} + {/* Removed Play Movie button from here */} + + + {/* Provider Information & Play Button Row */} + {(vod?.m3u_account || true) && ( + + {vod?.m3u_account && ( + + IPTV Provider + + + {vod.m3u_account.name} + + {vod.m3u_account.account_type && ( + + {vod.m3u_account.account_type === 'XC' ? 'Xtream Codes' : 'Standard M3U'} + + )} + + + )} + + + )} + {/* Technical Details */} + {(displayVOD.bitrate || displayVOD.video || displayVOD.audio) && ( + + Technical Details: + {displayVOD.bitrate && displayVOD.bitrate > 0 && ( + + Bitrate: {displayVOD.bitrate} kbps + + )} + {displayVOD.video && Object.keys(displayVOD.video).length > 0 && ( + + Video:{' '} + {displayVOD.video.codec_long_name || displayVOD.video.codec_name} + {displayVOD.video.profile ? ` (${displayVOD.video.profile})` : ''} + {displayVOD.video.width && displayVOD.video.height + ? `, ${displayVOD.video.width}x${displayVOD.video.height}` + : ''} + {displayVOD.video.display_aspect_ratio + ? `, Aspect Ratio: ${displayVOD.video.display_aspect_ratio}` + : ''} + {displayVOD.video.bit_rate + ? `, Bitrate: ${Math.round(Number(displayVOD.video.bit_rate) / 1000)} kbps` + : ''} + {displayVOD.video.r_frame_rate + ? `, Frame Rate: ${displayVOD.video.r_frame_rate.replace('/', '/')} fps` + : ''} + {displayVOD.video.tags?.encoder + ? `, Encoder: ${displayVOD.video.tags.encoder}` + : ''} + + )} + {displayVOD.audio && Object.keys(displayVOD.audio).length > 0 && ( + + Audio:{' '} + {displayVOD.audio.codec_long_name || displayVOD.audio.codec_name} + {displayVOD.audio.profile ? ` (${displayVOD.audio.profile})` : ''} + {displayVOD.audio.channel_layout + ? `, Channels: ${displayVOD.audio.channel_layout}` + : displayVOD.audio.channels + ? `, Channels: ${displayVOD.audio.channels}` + : ''} + {displayVOD.audio.sample_rate + ? `, Sample Rate: ${displayVOD.audio.sample_rate} Hz` + : ''} + {displayVOD.audio.bit_rate + ? `, Bitrate: ${Math.round(Number(displayVOD.audio.bit_rate) / 1000)} kbps` + : ''} + {displayVOD.audio.tags?.handler_name + ? `, Handler: ${displayVOD.audio.tags.handler_name}` + : ''} + + )} + + )} + {/* YouTube trailer if available */} + + + + + {/* YouTube Trailer Modal */} + setTrailerModalOpened(false)} + title="Trailer" + size="xl" + centered + withCloseButton + > + + {trailerUrl && ( +