import React, { useState, useEffect } from 'react'; import { View, Text, TouchableOpacity, ScrollView, useWindowDimensions, StyleSheet, Platform, ActivityIndicator } from 'react-native'; import { MaterialIcons } from '@expo/vector-icons'; import Animated, { FadeIn, FadeOut, SlideInRight, SlideOutRight, } from 'react-native-reanimated'; import { useTranslation } from 'react-i18next'; import { Episode } from '../../../types/metadata'; import { EpisodeCard } from '../cards/EpisodeCard'; import { storageService } from '../../../services/storageService'; import { TraktService } from '../../../services/traktService'; import { logger } from '../../../utils/logger'; interface EpisodesModalProps { showEpisodesModal: boolean; setShowEpisodesModal: (show: boolean) => void; groupedEpisodes: { [seasonNumber: number]: Episode[] }; currentEpisode?: { season: number; episode: number }; metadata?: { poster?: string; id?: string; tmdbId?: string; type?: string }; onSelectEpisode: (episode: Episode) => void; tmdbEpisodeOverrides?: any; } export const EpisodesModal: React.FC = ({ showEpisodesModal, setShowEpisodesModal, groupedEpisodes, currentEpisode, metadata, onSelectEpisode, tmdbEpisodeOverrides }) => { const { t } = useTranslation(); const { width } = useWindowDimensions(); const [selectedSeason, setSelectedSeason] = useState(currentEpisode?.season || 1); const [episodeProgress, setEpisodeProgress] = useState<{ [key: string]: any }>({}); const [isLoadingProgress, setIsLoadingProgress] = useState(false); const MENU_WIDTH = Math.min(width * 0.85, 400); const currentTheme = { colors: { text: '#FFFFFF', textMuted: 'rgba(255,255,255,0.6)', mediumEmphasis: 'rgba(255,255,255,0.7)', primary: 'rgba(255,255,255,0.9)', white: '#FFFFFF', elevation2: 'rgba(255,255,255,0.05)' } }; // Logic Preserved: Fetch progress from storage/Trakt useEffect(() => { const fetchProgress = async () => { if (showEpisodesModal && metadata?.id) { setIsLoadingProgress(true); try { // Get all watch progress and filter for this show's episodes const allProgress = await storageService.getAllWatchProgress(); const showPrefix = `series:${metadata.id}:`; const progress: { [key: string]: any } = {}; for (const [key, value] of Object.entries(allProgress)) { if (key.startsWith(showPrefix)) { // Extract episode id from key (format: series:showId:episodeId) const episodeId = key.replace(showPrefix, ''); progress[episodeId] = value; } } setEpisodeProgress(progress); // Trakt sync logic preserved if (await TraktService.getInstance().isAuthenticated()) { // Optional: background sync logic } } catch (err) { logger.error('Failed to fetch episode progress', err); } finally { setIsLoadingProgress(false); } } }; fetchProgress(); }, [showEpisodesModal, metadata?.id]); useEffect(() => { if (showEpisodesModal && currentEpisode?.season) { setSelectedSeason(currentEpisode.season); } }, [showEpisodesModal]); if (!showEpisodesModal) return null; const seasons = Object.keys(groupedEpisodes).map(Number).sort((a, b) => a - b); const currentSeasonEpisodes = groupedEpisodes[selectedSeason] || []; return ( setShowEpisodesModal(false)}> {t('player_ui.episodes')} {[...seasons] .sort((a, b) => { if (a === 0) return 1; if (b === 0) return -1; return a - b; }).map((season) => ( setSelectedSeason(season)} style={{ paddingHorizontal: 16, paddingVertical: 8, borderRadius: 20, backgroundColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.06)', borderWidth: 1, borderColor: selectedSeason === season ? 'white' : 'rgba(255,255,255,0.1)', }} > {season === 0 ? t('player_ui.specials') : t('player_ui.season', { season })} ))} {isLoadingProgress ? ( ) : ( {currentSeasonEpisodes.map((episode) => ( { onSelectEpisode(episode); setShowEpisodesModal(false); }} currentTheme={currentTheme} isCurrent={currentEpisode?.season === episode.season_number && currentEpisode?.episode === episode.episode_number} /> ))} )} ); }; export default EpisodesModal;