mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-01-11 20:10:25 +00:00
CP!!! Some changes top trakt
This commit is contained in:
parent
6d661f6c85
commit
fde8904c3b
3 changed files with 126 additions and 4 deletions
|
|
@ -254,6 +254,62 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
|
|||
// Wait for all content to be processed
|
||||
await Promise.all(contentPromises);
|
||||
|
||||
// -------------------- TRAKT HISTORY INTEGRATION --------------------
|
||||
try {
|
||||
const traktService = TraktService.getInstance();
|
||||
const isAuthed = await traktService.isAuthenticated();
|
||||
if (isAuthed) {
|
||||
const historyItems = await traktService.getWatchedEpisodesHistory(1, 200);
|
||||
const latestWatchedByShow: Record<string, { season: number; episode: number; watchedAt: number }> = {};
|
||||
|
||||
for (const item of historyItems) {
|
||||
if (item.type !== 'episode') continue;
|
||||
const showImdb = item.show?.ids?.imdb ? `tt${item.show.ids.imdb.replace(/^tt/, '')}` : null;
|
||||
if (!showImdb) continue;
|
||||
|
||||
const season = item.episode?.season;
|
||||
const epNum = item.episode?.number;
|
||||
if (season === undefined || epNum === undefined) continue;
|
||||
const watchedAt = new Date(item.watched_at).getTime();
|
||||
|
||||
const existing = latestWatchedByShow[showImdb];
|
||||
if (!existing || existing.watchedAt < watchedAt) {
|
||||
latestWatchedByShow[showImdb] = { season, episode: epNum, watchedAt };
|
||||
}
|
||||
}
|
||||
|
||||
// Create placeholders for each show if not already present
|
||||
for (const [showId, info] of Object.entries(latestWatchedByShow)) {
|
||||
if (latestEpisodes[showId]) continue; // already handled via progress
|
||||
|
||||
const nextEpisode = info.episode + 1;
|
||||
const nextEpisodeId = `${showId}:${info.season}:${nextEpisode}`;
|
||||
|
||||
try {
|
||||
const basicContent = await catalogService.getBasicContentDetails('series', showId);
|
||||
if (!basicContent) continue;
|
||||
|
||||
const placeholder: ContinueWatchingItem = {
|
||||
...basicContent,
|
||||
id: showId,
|
||||
type: 'series',
|
||||
progress: 0,
|
||||
lastUpdated: info.watchedAt,
|
||||
season: info.season,
|
||||
episode: nextEpisode,
|
||||
episodeTitle: `Episode ${nextEpisode}`,
|
||||
} as ContinueWatchingItem;
|
||||
|
||||
latestEpisodes[showId] = placeholder;
|
||||
} catch (err) {
|
||||
logger.error('Failed to build placeholder from history:', err);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Error merging Trakt history:', err);
|
||||
}
|
||||
|
||||
// Add the latest episodes for each series to the items list
|
||||
progressItems.push(...Object.values(latestEpisodes));
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import { tmdbService } from '../../services/tmdbService';
|
|||
import { storageService } from '../../services/storageService';
|
||||
import { useFocusEffect } from '@react-navigation/native';
|
||||
import Animated, { FadeIn } from 'react-native-reanimated';
|
||||
import { TraktService } from '../../services/traktService';
|
||||
import { logger } from '../../utils/logger';
|
||||
|
||||
interface SeriesContentProps {
|
||||
episodes: Episode[];
|
||||
|
|
@ -66,6 +68,46 @@ export const SeriesContent: React.FC<SeriesContentProps> = ({
|
|||
}
|
||||
});
|
||||
|
||||
// ---------------- Trakt watched-history integration ----------------
|
||||
try {
|
||||
const traktService = TraktService.getInstance();
|
||||
const isAuthed = await traktService.isAuthenticated();
|
||||
if (isAuthed && metadata?.id) {
|
||||
const historyItems = await traktService.getWatchedEpisodesHistory(1, 400);
|
||||
|
||||
historyItems.forEach(item => {
|
||||
if (item.type !== 'episode') return;
|
||||
|
||||
const showImdb = item.show?.ids?.imdb ? `tt${item.show.ids.imdb.replace(/^tt/, '')}` : null;
|
||||
if (!showImdb || showImdb !== metadata.id) return;
|
||||
|
||||
const season = item.episode?.season;
|
||||
const epNum = item.episode?.number;
|
||||
if (season === undefined || epNum === undefined) return;
|
||||
|
||||
const episodeId = `${metadata.id}:${season}:${epNum}`;
|
||||
const watchedAt = new Date(item.watched_at).getTime();
|
||||
|
||||
// Mark as 100% completed (use 1/1 to avoid divide-by-zero)
|
||||
const traktProgressEntry = {
|
||||
currentTime: 1,
|
||||
duration: 1,
|
||||
lastUpdated: watchedAt,
|
||||
};
|
||||
|
||||
const existing = progress[episodeId];
|
||||
const existingPercent = existing ? (existing.currentTime / existing.duration) * 100 : 0;
|
||||
|
||||
// Prefer local progress if it is already >=85%; otherwise use Trakt data
|
||||
if (!existing || existingPercent < 85) {
|
||||
progress[episodeId] = traktProgressEntry;
|
||||
}
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('[SeriesContent] Failed to merge Trakt history:', err);
|
||||
}
|
||||
|
||||
setEpisodeProgress(progress);
|
||||
};
|
||||
|
||||
|
|
@ -799,8 +841,8 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
completedBadge: {
|
||||
position: 'absolute',
|
||||
bottom: 8,
|
||||
right: 8,
|
||||
top: 8,
|
||||
left: 8,
|
||||
width: 20,
|
||||
height: 20,
|
||||
borderRadius: 10,
|
||||
|
|
@ -808,6 +850,7 @@ const styles = StyleSheet.create({
|
|||
justifyContent: 'center',
|
||||
borderWidth: 1,
|
||||
borderColor: 'rgba(255,255,255,0.3)',
|
||||
zIndex: 2,
|
||||
},
|
||||
|
||||
// Horizontal Layout Styles
|
||||
|
|
@ -935,8 +978,8 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
completedBadgeHorizontal: {
|
||||
position: 'absolute',
|
||||
bottom: 12,
|
||||
right: 12,
|
||||
top: 12,
|
||||
left: 12,
|
||||
width: 24,
|
||||
height: 24,
|
||||
borderRadius: 12,
|
||||
|
|
|
|||
|
|
@ -1562,6 +1562,29 @@ export class TraktService {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async getWatchedEpisodesHistory(page: number = 1, limit: number = 100): Promise<any[]> {
|
||||
await this.ensureInitialized();
|
||||
|
||||
const cacheKey = `history_episodes_${page}_${limit}`;
|
||||
const lastSync = this.lastSyncTimes.get(cacheKey) || 0;
|
||||
const now = Date.now();
|
||||
if (now - lastSync < this.SYNC_DEBOUNCE_MS) {
|
||||
// Return cached result if we fetched recently
|
||||
return (this as any)[cacheKey] || [];
|
||||
}
|
||||
|
||||
const endpoint = `/sync/history/episodes?page=${page}&limit=${limit}`;
|
||||
try {
|
||||
const data = await this.apiRequest<any[]>(endpoint, 'GET');
|
||||
(this as any)[cacheKey] = data;
|
||||
this.lastSyncTimes.set(cacheKey, now);
|
||||
return data;
|
||||
} catch (error) {
|
||||
logger.error('[TraktService] Failed to fetch watched episodes history:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Export a singleton instance
|
||||
|
|
|
|||
Loading…
Reference in a new issue