Merge pull request #355 from chrisk325/patch-7

This commit is contained in:
Nayif 2026-01-04 11:13:38 +05:30 committed by GitHub
commit 3d5a9ebf42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 126 additions and 27 deletions

View file

@ -376,7 +376,10 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
const [type, id, ...episodeIdParts] = keyParts;
const episodeId = episodeIdParts.length > 0 ? episodeIdParts.join(':') : undefined;
const progress = allProgress[key];
const progressPercent = (progress.currentTime / progress.duration) * 100;
const progressPercent =
progress.duration > 0
? (progress.currentTime / progress.duration) * 100
: 0;
// Skip fully watched movies
if (type === 'movie' && progressPercent >= 85) continue;
// Skip movies with no actual progress (ensure > 0%)
@ -469,7 +472,10 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
// Skip movies that are already watched on Trakt
if (group.type === 'movie') {
const watchedSet = await traktMoviesSetPromise;
if (watchedSet.has(group.id)) {
const imdbId = group.id.startsWith('tt')
? group.id
: `tt${group.id}`;
if (watchedSet.has(imdbId)) {
// Optional: sync local store to watched to prevent reappearance
try {
await storageService.setWatchProgress(group.id, 'movie', {
@ -1198,7 +1204,6 @@ const ContinueWatchingSection = React.forwardRef<ContinueWatchingRef>((props, re
padding: isTV ? 16 : isLargeTablet ? 14 : isTablet ? 12 : 12
}
]}>
<View style={styles.titleRow}>
{(() => {
const isUpNext = item.type === 'series' && item.progress === 0;
return (

View file

@ -1102,48 +1102,142 @@ export class TraktService {
public async isMovieWatchedAccurate(imdbId: string): Promise<boolean> {
try {
const history = await this.client.get(
`/sync/history/movies/${imdbId}?limit=1`
const imdb = imdbId.startsWith('tt')
? imdbId
: `tt${imdbId}`;
const response = await this.client.get('/sync/watched/movies');
const movies = Array.isArray(response.data) ? response.data : [];
return movies.some(
(m: any) => m.movie?.ids?.imdb === imdb
);
const history = response.data;
return Array.isArray(history) && history.length > 0;
} catch {
} catch (err) {
logger.warn('[TraktService] Movie watched check failed', err);
return false;
}
}
public async isEpisodeWatchedAccurate(
showId: string,
showImdbId: string,
season: number,
episode: number
): Promise<boolean> {
try {
const history = await this.client.get(
`/sync/history/episodes/${showId}`,
{ params: { limit: 20 } }
);
const history = response.data;
if (!Array.isArray(history)) return false;
if (season === 0) return false;
const imdb = showImdbId.startsWith('tt')
? showImdbId
: `tt${showImdbId}`;
const watchedShows = await this.apiRequest<any[]>(
'/sync/watched/shows'
);
const show = watchedShows.find(
s => s.show?.ids?.imdb === imdb
);
if (show) {
const seasonData = show.seasons?.find(
(s: any) => s.number === season
);
for (const entry of history) {
if (
entry.episode?.season === season &&
entry.episode?.number === episode
seasonData?.episodes?.some(
(e: any) => e.number === episode
)
) {
if (entry.reset_at) {
const watchedAt = new Date(entry.watched_at).getTime();
const resetAt = new Date(entry.reset_at).getTime();
if (watchedAt < resetAt) return false;
}
return true;
}
}
let page = 1;
while (true) {
const history = await this.apiRequest<any[]>(
`/sync/history/shows/${imdb}?page=${page}&limit=100`
);
if (!history.length) break;
if (
history.some(
(h: any) =>
h.episode?.season === season &&
h.episode?.number === episode
)
) {
return true;
}
page++;
}
return false;
} catch {
} catch (err) {
logger.warn('[TraktService] Episode watched check failed', err);
return false;
}
}
public async isSeasonCompletedAccurate(
showImdbId: string,
seasonNumber: number,
totalAiredEpisodes: number
): Promise<boolean> {
try {
if (seasonNumber === 0) return false;
if (!totalAiredEpisodes || totalAiredEpisodes <= 0) return false;
const imdb = showImdbId.startsWith('tt')
? showImdbId
: `tt${showImdbId}`;
const watchedEpisodes = new Set<number>();
const watchedShows = await this.apiRequest<any[]>(
'/sync/watched/shows'
);
const show = watchedShows.find(
s => s.show?.ids?.imdb === imdb
);
if (show) {
const season = show.seasons?.find(
(s: any) => s.number === seasonNumber
);
season?.episodes?.forEach(
(e: any) => watchedEpisodes.add(e.number)
);
}
let page = 1;
while (true) {
const history = await this.apiRequest<any[]>(
`/sync/history/shows/${imdb}?page=${page}&limit=10`
);
if (!history.length) break;
history.forEach((h: any) => {
if (
h.episode?.season === seasonNumber &&
typeof h.episode?.number === 'number'
) {
watchedEpisodes.add(h.episode.number);
}
});
page++;
}
return watchedEpisodes.size >= totalAiredEpisodes;
} catch (err) {
logger.warn('[TraktService] Season completion check failed', err);
return false;
}
}