fix: improve resume position handling in player and trakt progress logic

This commit is contained in:
tapframe 2026-04-06 14:09:13 +05:30
parent f7071e1fc2
commit b1d9e2dc93
3 changed files with 23 additions and 21 deletions

View file

@ -507,15 +507,8 @@ fun PlayerScreen(
fun switchToSource(stream: StreamItem) {
val url = stream.directPlaybackUrl ?: return
if (url == activeSourceUrl) return
val currentPositionMs = playbackSnapshot.positionMs.coerceAtLeast(0L)
flushWatchProgress()
val resumeVideoId = buildPlaybackVideoId(
parentMetaId = parentMetaId,
seasonNumber = activeSeasonNumber,
episodeNumber = activeEpisodeNumber,
fallbackVideoId = activeVideoId,
)
val entry = WatchProgressRepository.progressForVideo(resumeVideoId)
val resumePositionMs = entry?.lastPositionMs?.takeIf { it > 0L } ?: 0L
if (playerSettingsUiState.streamReuseLastLinkEnabled && activeVideoId != null) {
val cacheKey = StreamLinkCacheRepository.contentKey(
contentType ?: parentMetaType,
@ -538,7 +531,7 @@ fun PlayerScreen(
activeStreamSubtitle = stream.streamSubtitle
activeProviderName = stream.addonName
activeProviderAddonId = stream.addonId
activeInitialPositionMs = resumePositionMs
activeInitialPositionMs = currentPositionMs
activeInitialProgressFraction = null
showSourcesPanel = false
controlsVisible = true
@ -564,9 +557,11 @@ fun PlayerScreen(
fallbackVideoId = epVideoId,
)
val epEntry = WatchProgressRepository.progressForVideo(epResumeVideoId)
val epResumePositionMs = epEntry
?.takeIf { !it.isCompleted }
?.lastPositionMs?.takeIf { it > 0L } ?: 0L
val epResumeFraction = epEntry?.progressPercent
?.takeIf { it > 0f }
?.let { (it / 100f).coerceIn(0f, 1f) }
val epResumePositionMs = epEntry?.lastPositionMs?.takeIf { it > 0L } ?: 0L
if (playerSettingsUiState.streamReuseLastLinkEnabled) {
val cacheKey = StreamLinkCacheRepository.contentKey(
contentType ?: parentMetaType,
@ -595,7 +590,7 @@ fun PlayerScreen(
activeEpisodeThumbnail = episode.thumbnail
activeVideoId = episode.id
activeInitialPositionMs = epResumePositionMs
activeInitialProgressFraction = null
activeInitialProgressFraction = epResumeFraction
controlsVisible = true
}

View file

@ -26,7 +26,6 @@ import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
private const val BASE_URL = "https://api.trakt.tv"
private const val PLAYBACK_SYNTHETIC_DURATION_MS = 100_000L
private const val HISTORY_LIMIT = 250
private const val METADATA_FETCH_TIMEOUT_MS = 3_500L
private const val METADATA_FETCH_CONCURRENCY = 5
@ -356,8 +355,6 @@ object TraktProgressRepository {
val progressPercent = normalizeTraktProgressPercent(item.progress) ?: return null
if (progressPercent <= 0f) return null
val progressFraction = progressPercent / 100f
val positionMs = (PLAYBACK_SYNTHETIC_DURATION_MS * progressFraction).toLong()
return WatchProgressEntry(
contentType = "movie",
@ -365,8 +362,8 @@ object TraktProgressRepository {
parentMetaType = "movie",
videoId = parentMetaId,
title = movie.title ?: parentMetaId,
lastPositionMs = positionMs,
durationMs = PLAYBACK_SYNTHETIC_DURATION_MS,
lastPositionMs = 0L,
durationMs = 0L,
lastUpdatedEpochMs = rankedTimestamp(item.pausedAt, fallbackIndex),
isCompleted = false,
progressPercent = progressPercent,
@ -384,8 +381,6 @@ object TraktProgressRepository {
val progressPercent = normalizeTraktProgressPercent(item.progress) ?: return null
if (progressPercent <= 0f) return null
val progressFraction = progressPercent / 100f
val positionMs = (PLAYBACK_SYNTHETIC_DURATION_MS * progressFraction).toLong()
return WatchProgressEntry(
contentType = "series",
@ -401,8 +396,8 @@ object TraktProgressRepository {
seasonNumber = season,
episodeNumber = number,
episodeTitle = episode.title,
lastPositionMs = positionMs,
durationMs = PLAYBACK_SYNTHETIC_DURATION_MS,
lastPositionMs = 0L,
durationMs = 0L,
lastUpdatedEpochMs = rankedTimestamp(item.pausedAt, fallbackIndex),
isCompleted = false,
progressPercent = progressPercent,

View file

@ -53,6 +53,18 @@ data class WatchProgressEntry(
val isResumable: Boolean
get() = !isCompleted
fun resolveResumePosition(actualDurationMs: Long): Long {
if (actualDurationMs <= 0L) return lastPositionMs.coerceAtLeast(0L)
if (durationMs > 0L && lastPositionMs > 0L) {
return lastPositionMs.coerceIn(0L, actualDurationMs)
}
progressPercent?.let { percent ->
val fraction = (percent / 100f).coerceIn(0f, 1f)
return (actualDurationMs * fraction).toLong()
}
return lastPositionMs.coerceAtLeast(0L)
}
}
data class WatchProgressUiState(