From 952c8760254d70871edf807c1df5702d362cb4a3 Mon Sep 17 00:00:00 2001 From: EierKopZA Date: Fri, 15 May 2026 16:20:08 +0200 Subject: [PATCH] fix: initialize watched cache before fetchSeasonProgress to prevent race condition --- .../tv/ui/screens/details/DetailsViewModel.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt index 33734ddb5..27298bd8e 100644 --- a/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt +++ b/app/src/main/kotlin/com/arflix/tv/ui/screens/details/DetailsViewModel.kt @@ -317,7 +317,16 @@ class DetailsViewModel @Inject constructor( async { mediaRepository.getSeasonEpisodes(mediaId, seasonToLoad) } } else null - // For TV shows, fetch season progress (watched/total per season) + // For TV shows, fetch season progress (watched/total per season). + // IMPORTANT: Initialize watched cache FIRST so fetchSeasonProgress() + // can read from the in-memory cache rather than falling back to a + // backend query that may return stale or empty data. The async below + // starts immediately, but initializeWatchedCache() runs synchronously + // before it, ensuring the cache is populated before fetchSeasonProgress + // checks getWatchedEpisodesFromCache(). + if (mediaType == MediaType.TV) { + runCatching { traktRepository.initializeWatchedCache() } + } val seasonProgressDeferred = if (mediaType == MediaType.TV) { async { fetchSeasonProgress(mediaId) } } else null @@ -1587,12 +1596,15 @@ class DetailsViewModel @Inject constructor( traktRepository.markSeasonWatched(currentMediaId, season, episodeNumbers) } - // 2. Remove from watch history concurrently (all episodes at once) + // 2. Remove from watch history FIRST (synchronous), before Supabase writes. + // This avoids a race condition where removeFromHistory deletes the + // just-written watched records, causing watched status to be lost on re-entry. runCatching { watchHistoryRepository.removeFromHistory(currentMediaId, season, null) } - // 3. Concurrent Supabase writes for each episode (faster than sequential) + // 3. Concurrent Supabase writes for each episode (faster than sequential). + // These run AFTER removeFromHistory to ensure the watched records are the final state. episodeNumbers.map { epNum -> async { runCatching {