mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-04-20 16:22:04 +00:00
CP, calender changes
This commit is contained in:
parent
93e80d9720
commit
fe8489fa18
4 changed files with 192 additions and 31 deletions
|
|
@ -14,6 +14,7 @@ import { Image } from 'expo-image';
|
||||||
import { LinearGradient } from 'expo-linear-gradient';
|
import { LinearGradient } from 'expo-linear-gradient';
|
||||||
import { MaterialIcons } from '@expo/vector-icons';
|
import { MaterialIcons } from '@expo/vector-icons';
|
||||||
import { useTheme } from '../../contexts/ThemeContext';
|
import { useTheme } from '../../contexts/ThemeContext';
|
||||||
|
import { useTraktContext } from '../../contexts/TraktContext';
|
||||||
import { stremioService } from '../../services/stremioService';
|
import { stremioService } from '../../services/stremioService';
|
||||||
import { tmdbService } from '../../services/tmdbService';
|
import { tmdbService } from '../../services/tmdbService';
|
||||||
import { useLibrary } from '../../hooks/useLibrary';
|
import { useLibrary } from '../../hooks/useLibrary';
|
||||||
|
|
@ -44,23 +45,75 @@ interface ThisWeekEpisode {
|
||||||
export const ThisWeekSection = React.memo(() => {
|
export const ThisWeekSection = React.memo(() => {
|
||||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
const { libraryItems, loading: libraryLoading } = useLibrary();
|
const { libraryItems, loading: libraryLoading } = useLibrary();
|
||||||
|
const {
|
||||||
|
isAuthenticated: traktAuthenticated,
|
||||||
|
isLoading: traktLoading,
|
||||||
|
watchedShows,
|
||||||
|
watchlistShows,
|
||||||
|
continueWatching,
|
||||||
|
loadAllCollections
|
||||||
|
} = useTraktContext();
|
||||||
const [episodes, setEpisodes] = useState<ThisWeekEpisode[]>([]);
|
const [episodes, setEpisodes] = useState<ThisWeekEpisode[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
|
|
||||||
const fetchThisWeekEpisodes = useCallback(async () => {
|
const fetchThisWeekEpisodes = useCallback(async () => {
|
||||||
if (libraryItems.length === 0) {
|
|
||||||
setLoading(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const seriesItems = libraryItems.filter(item => item.type === 'series');
|
// Combine library series with Trakt series
|
||||||
|
const librarySeries = libraryItems.filter(item => item.type === 'series');
|
||||||
|
let allSeries = [...librarySeries];
|
||||||
|
|
||||||
|
// Add Trakt watchlist and continue watching shows if authenticated
|
||||||
|
if (traktAuthenticated) {
|
||||||
|
const traktSeriesIds = new Set();
|
||||||
|
|
||||||
|
// Add watchlist shows
|
||||||
|
if (watchlistShows) {
|
||||||
|
for (const item of watchlistShows) {
|
||||||
|
if (item.show && item.show.ids.imdb) {
|
||||||
|
const imdbId = item.show.ids.imdb;
|
||||||
|
if (!librarySeries.some(s => s.id === imdbId)) {
|
||||||
|
traktSeriesIds.add(imdbId);
|
||||||
|
allSeries.push({
|
||||||
|
id: imdbId,
|
||||||
|
name: item.show.title,
|
||||||
|
type: 'series',
|
||||||
|
poster: '', // Will try to fetch from TMDB
|
||||||
|
year: item.show.year,
|
||||||
|
traktSource: 'watchlist'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add continue watching shows
|
||||||
|
if (continueWatching) {
|
||||||
|
for (const item of continueWatching) {
|
||||||
|
if (item.type === 'episode' && item.show && item.show.ids.imdb) {
|
||||||
|
const imdbId = item.show.ids.imdb;
|
||||||
|
if (!librarySeries.some(s => s.id === imdbId) && !traktSeriesIds.has(imdbId)) {
|
||||||
|
traktSeriesIds.add(imdbId);
|
||||||
|
allSeries.push({
|
||||||
|
id: imdbId,
|
||||||
|
name: item.show.title,
|
||||||
|
type: 'series',
|
||||||
|
poster: '', // Will try to fetch from TMDB
|
||||||
|
year: item.show.year,
|
||||||
|
traktSource: 'continue-watching'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`[ThisWeekSection] Checking ${allSeries.length} series (Library: ${librarySeries.length}, Trakt: ${allSeries.length - librarySeries.length})`);
|
||||||
let allEpisodes: ThisWeekEpisode[] = [];
|
let allEpisodes: ThisWeekEpisode[] = [];
|
||||||
|
|
||||||
for (const series of seriesItems) {
|
for (const series of allSeries) {
|
||||||
try {
|
try {
|
||||||
const metadata = await stremioService.getMetaDetails(series.type, series.id);
|
const metadata = await stremioService.getMetaDetails(series.type, series.id);
|
||||||
|
|
||||||
|
|
@ -125,15 +178,23 @@ export const ThisWeekSection = React.memo(() => {
|
||||||
} finally {
|
} finally {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [libraryItems]);
|
}, [libraryItems, traktAuthenticated, watchlistShows, continueWatching]);
|
||||||
|
|
||||||
// Load episodes when library items change
|
// Load episodes when library items or Trakt data changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!libraryLoading) {
|
if (!libraryLoading && !traktLoading) {
|
||||||
console.log('[ThisWeekSection] Library items changed, refreshing episodes. Items count:', libraryItems.length);
|
if (traktAuthenticated && (!watchlistShows || !continueWatching)) {
|
||||||
|
console.log('[ThisWeekSection] Loading Trakt collections for this week data');
|
||||||
|
loadAllCollections();
|
||||||
|
} else {
|
||||||
|
console.log('[ThisWeekSection] Data ready, refreshing episodes. Library items:', libraryItems.length);
|
||||||
|
fetchThisWeekEpisodes();
|
||||||
|
}
|
||||||
|
} else if (!libraryLoading && !traktAuthenticated) {
|
||||||
|
console.log('[ThisWeekSection] Not authenticated with Trakt, using library only. Items count:', libraryItems.length);
|
||||||
fetchThisWeekEpisodes();
|
fetchThisWeekEpisodes();
|
||||||
}
|
}
|
||||||
}, [libraryLoading, libraryItems, fetchThisWeekEpisodes]);
|
}, [libraryLoading, traktLoading, traktAuthenticated, libraryItems, watchlistShows, continueWatching, fetchThisWeekEpisodes, loadAllCollections]);
|
||||||
|
|
||||||
const handleEpisodePress = (episode: ThisWeekEpisode) => {
|
const handleEpisodePress = (episode: ThisWeekEpisode) => {
|
||||||
// For upcoming episodes, go to the metadata screen
|
// For upcoming episodes, go to the metadata screen
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ import { useTheme } from '../contexts/ThemeContext';
|
||||||
import { RootStackParamList } from '../navigation/AppNavigator';
|
import { RootStackParamList } from '../navigation/AppNavigator';
|
||||||
import { stremioService } from '../services/stremioService';
|
import { stremioService } from '../services/stremioService';
|
||||||
import { useLibrary } from '../hooks/useLibrary';
|
import { useLibrary } from '../hooks/useLibrary';
|
||||||
|
import { useTraktContext } from '../contexts/TraktContext';
|
||||||
import { format, parseISO, isThisWeek, isAfter, startOfToday, addWeeks, isBefore, isSameDay } from 'date-fns';
|
import { format, parseISO, isThisWeek, isAfter, startOfToday, addWeeks, isBefore, isSameDay } from 'date-fns';
|
||||||
import Animated, { FadeIn } from 'react-native-reanimated';
|
import Animated, { FadeIn } from 'react-native-reanimated';
|
||||||
import { CalendarSection } from '../components/calendar/CalendarSection';
|
import { CalendarSection } from '../components/calendar/CalendarSection';
|
||||||
|
|
@ -55,6 +56,15 @@ const CalendarScreen = () => {
|
||||||
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
const navigation = useNavigation<NavigationProp<RootStackParamList>>();
|
||||||
const { libraryItems, loading: libraryLoading } = useLibrary();
|
const { libraryItems, loading: libraryLoading } = useLibrary();
|
||||||
const { currentTheme } = useTheme();
|
const { currentTheme } = useTheme();
|
||||||
|
const {
|
||||||
|
isAuthenticated: traktAuthenticated,
|
||||||
|
isLoading: traktLoading,
|
||||||
|
watchedShows,
|
||||||
|
watchlistShows,
|
||||||
|
continueWatching,
|
||||||
|
loadAllCollections
|
||||||
|
} = useTraktContext();
|
||||||
|
|
||||||
logger.log(`[Calendar] Initial load - Library has ${libraryItems?.length || 0} items, loading: ${libraryLoading}`);
|
logger.log(`[Calendar] Initial load - Library has ${libraryItems?.length || 0} items, loading: ${libraryLoading}`);
|
||||||
const [calendarData, setCalendarData] = useState<CalendarSection[]>([]);
|
const [calendarData, setCalendarData] = useState<CalendarSection[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
|
|
@ -67,15 +77,83 @@ const CalendarScreen = () => {
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Filter for only series in library
|
// Combine library series with Trakt series
|
||||||
const seriesItems = libraryItems.filter(item => item.type === 'series');
|
const librarySeries = libraryItems.filter(item => item.type === 'series');
|
||||||
logger.log(`[Calendar] Library items: ${libraryItems.length}, Series items: ${seriesItems.length}`);
|
let allSeries = [...librarySeries];
|
||||||
|
|
||||||
|
// Add Trakt watchlist and watched shows if authenticated
|
||||||
|
if (traktAuthenticated) {
|
||||||
|
const traktSeriesIds = new Set();
|
||||||
|
|
||||||
|
// Add watchlist shows
|
||||||
|
if (watchlistShows) {
|
||||||
|
for (const item of watchlistShows) {
|
||||||
|
if (item.show && item.show.ids.imdb) {
|
||||||
|
const imdbId = item.show.ids.imdb;
|
||||||
|
if (!librarySeries.some(s => s.id === imdbId)) {
|
||||||
|
traktSeriesIds.add(imdbId);
|
||||||
|
allSeries.push({
|
||||||
|
id: imdbId,
|
||||||
|
name: item.show.title,
|
||||||
|
type: 'series',
|
||||||
|
poster: '', // Will try to fetch from TMDB
|
||||||
|
year: item.show.year,
|
||||||
|
traktSource: 'watchlist'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add continue watching shows
|
||||||
|
if (continueWatching) {
|
||||||
|
for (const item of continueWatching) {
|
||||||
|
if (item.type === 'episode' && item.show && item.show.ids.imdb) {
|
||||||
|
const imdbId = item.show.ids.imdb;
|
||||||
|
if (!librarySeries.some(s => s.id === imdbId) && !traktSeriesIds.has(imdbId)) {
|
||||||
|
traktSeriesIds.add(imdbId);
|
||||||
|
allSeries.push({
|
||||||
|
id: imdbId,
|
||||||
|
name: item.show.title,
|
||||||
|
type: 'series',
|
||||||
|
poster: '', // Will try to fetch from TMDB
|
||||||
|
year: item.show.year,
|
||||||
|
traktSource: 'continue-watching'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add watched shows (only recent ones to avoid too much data)
|
||||||
|
if (watchedShows) {
|
||||||
|
const recentWatched = watchedShows.slice(0, 20); // Limit to recent 20
|
||||||
|
for (const item of recentWatched) {
|
||||||
|
if (item.show && item.show.ids.imdb) {
|
||||||
|
const imdbId = item.show.ids.imdb;
|
||||||
|
if (!librarySeries.some(s => s.id === imdbId) && !traktSeriesIds.has(imdbId)) {
|
||||||
|
traktSeriesIds.add(imdbId);
|
||||||
|
allSeries.push({
|
||||||
|
id: imdbId,
|
||||||
|
name: item.show.title,
|
||||||
|
type: 'series',
|
||||||
|
poster: '', // Will try to fetch from TMDB
|
||||||
|
year: item.show.year,
|
||||||
|
traktSource: 'watched'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.log(`[Calendar] Total series to check: ${allSeries.length} (Library: ${librarySeries.length}, Trakt: ${allSeries.length - librarySeries.length})`);
|
||||||
|
|
||||||
let allEpisodes: CalendarEpisode[] = [];
|
let allEpisodes: CalendarEpisode[] = [];
|
||||||
let seriesWithoutEpisodes: CalendarEpisode[] = [];
|
let seriesWithoutEpisodes: CalendarEpisode[] = [];
|
||||||
|
|
||||||
// For each series, fetch upcoming episodes
|
// For each series, fetch upcoming episodes
|
||||||
for (const series of seriesItems) {
|
for (const series of allSeries) {
|
||||||
try {
|
try {
|
||||||
logger.log(`[Calendar] Fetching episodes for series: ${series.name} (${series.id})`);
|
logger.log(`[Calendar] Fetching episodes for series: ${series.name} (${series.id})`);
|
||||||
const metadata = await stremioService.getMetaDetails(series.type, series.id);
|
const metadata = await stremioService.getMetaDetails(series.type, series.id);
|
||||||
|
|
@ -215,17 +293,22 @@ const CalendarScreen = () => {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
setRefreshing(false);
|
setRefreshing(false);
|
||||||
}
|
}
|
||||||
}, [libraryItems]);
|
}, [libraryItems, traktAuthenticated, watchlistShows, continueWatching, watchedShows]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (libraryItems.length > 0 && !libraryLoading) {
|
if (!libraryLoading && !traktLoading) {
|
||||||
logger.log(`[Calendar] Library loaded with ${libraryItems.length} items, fetching calendar data`);
|
if (traktAuthenticated && (!watchlistShows || !continueWatching || !watchedShows)) {
|
||||||
|
logger.log(`[Calendar] Loading Trakt collections for calendar data`);
|
||||||
|
loadAllCollections();
|
||||||
|
} else {
|
||||||
|
logger.log(`[Calendar] Data ready, fetching calendar data - Library: ${libraryItems.length} items`);
|
||||||
|
fetchCalendarData();
|
||||||
|
}
|
||||||
|
} else if (!libraryLoading && !traktAuthenticated) {
|
||||||
|
logger.log(`[Calendar] Not authenticated with Trakt, using library only (${libraryItems.length} items)`);
|
||||||
fetchCalendarData();
|
fetchCalendarData();
|
||||||
} else if (!libraryLoading) {
|
|
||||||
logger.log(`[Calendar] Library loaded but empty (${libraryItems.length} items)`);
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
}, [libraryItems, libraryLoading, fetchCalendarData]);
|
}, [libraryItems, libraryLoading, traktLoading, traktAuthenticated, watchlistShows, continueWatching, watchedShows, fetchCalendarData, loadAllCollections]);
|
||||||
|
|
||||||
const onRefresh = useCallback(() => {
|
const onRefresh = useCallback(() => {
|
||||||
setRefreshing(true);
|
setRefreshing(true);
|
||||||
|
|
|
||||||
|
|
@ -913,7 +913,20 @@ const LibraryScreen = () => {
|
||||||
<View style={styles.headerSpacer} />
|
<View style={styles.headerSpacer} />
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Text style={[styles.headerTitle, { color: currentTheme.colors.white }]}>Library</Text>
|
<>
|
||||||
|
<Text style={[styles.headerTitle, { color: currentTheme.colors.white }]}>Library</Text>
|
||||||
|
<TouchableOpacity
|
||||||
|
style={[styles.calendarButton, { backgroundColor: currentTheme.colors.primary }]}
|
||||||
|
onPress={() => navigation.navigate('Calendar')}
|
||||||
|
activeOpacity={0.7}
|
||||||
|
>
|
||||||
|
<MaterialIcons
|
||||||
|
name="event"
|
||||||
|
size={24}
|
||||||
|
color={currentTheme.colors.white}
|
||||||
|
/>
|
||||||
|
</TouchableOpacity>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
|
|
@ -1224,6 +1237,17 @@ const styles = StyleSheet.create({
|
||||||
justifyContent: 'space-between',
|
justifyContent: 'space-between',
|
||||||
paddingHorizontal: 16,
|
paddingHorizontal: 16,
|
||||||
},
|
},
|
||||||
|
calendarButton: {
|
||||||
|
width: 44,
|
||||||
|
height: 44,
|
||||||
|
borderRadius: 22,
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
elevation: 3,
|
||||||
|
shadowOffset: { width: 0, height: 2 },
|
||||||
|
shadowOpacity: 0.2,
|
||||||
|
shadowRadius: 4,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export default LibraryScreen;
|
export default LibraryScreen;
|
||||||
|
|
@ -401,13 +401,6 @@ const SettingsScreen: React.FC = () => {
|
||||||
renderControl={ChevronRight}
|
renderControl={ChevronRight}
|
||||||
onPress={() => navigation.navigate('PlayerSettings')}
|
onPress={() => navigation.navigate('PlayerSettings')}
|
||||||
/>
|
/>
|
||||||
<SettingItem
|
|
||||||
title="Calendar"
|
|
||||||
description="Episode tracking"
|
|
||||||
icon="event"
|
|
||||||
renderControl={ChevronRight}
|
|
||||||
onPress={() => navigation.navigate('Calendar')}
|
|
||||||
/>
|
|
||||||
<SettingItem
|
<SettingItem
|
||||||
title="Notifications"
|
title="Notifications"
|
||||||
description="Episode reminders"
|
description="Episode reminders"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue