mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-07-26 14:32:28 +00:00
Fix Trakt progress watched precedence
This commit is contained in:
parent
94e1141bd1
commit
4b6a15c950
3 changed files with 90 additions and 13 deletions
|
|
@ -11,7 +11,7 @@ import com.nuvio.app.features.watchprogress.WatchProgressSourceTraktHistory
|
|||
import com.nuvio.app.features.watchprogress.WatchProgressSourceTraktPlayback
|
||||
import com.nuvio.app.features.watchprogress.WatchProgressSourceTraktShowProgress
|
||||
import com.nuvio.app.features.watchprogress.buildPlaybackVideoId
|
||||
import com.nuvio.app.features.watchprogress.shouldTreatAsInProgressForContinueWatching
|
||||
import com.nuvio.app.features.watchprogress.shouldReplaceProgressSnapshotEntry
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
|
|
@ -1007,18 +1007,6 @@ object TraktProgressRepository {
|
|||
.sortedByDescending { it.lastUpdatedEpochMs }
|
||||
}
|
||||
|
||||
private fun shouldReplaceProgressSnapshotEntry(
|
||||
existing: WatchProgressEntry,
|
||||
candidate: WatchProgressEntry,
|
||||
): Boolean {
|
||||
val existingInProgress = existing.shouldTreatAsInProgressForContinueWatching()
|
||||
val candidateInProgress = candidate.shouldTreatAsInProgressForContinueWatching()
|
||||
if (existingInProgress != candidateInProgress) {
|
||||
return candidateInProgress
|
||||
}
|
||||
return candidate.lastUpdatedEpochMs > existing.lastUpdatedEpochMs
|
||||
}
|
||||
|
||||
private fun mergeEntriesPreferRichMetadata(
|
||||
current: List<WatchProgressEntry>,
|
||||
hydrated: List<WatchProgressEntry>,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import kotlinx.serialization.encodeToString
|
|||
import kotlinx.serialization.json.Json
|
||||
|
||||
internal const val ContinueWatchingLimit = DefaultContinueWatchingLimit
|
||||
private const val WatchProgressSnapshotConflictToleranceMs = 1_000L
|
||||
|
||||
@Serializable
|
||||
internal data class StoredWatchProgressPayload(
|
||||
|
|
@ -124,6 +125,24 @@ internal fun WatchProgressEntry.shouldUseAsCompletedSeedForContinueWatching(): B
|
|||
return explicitPercent >= WatchProgressTraktPlaybackNextUpSeedPercentThreshold
|
||||
}
|
||||
|
||||
internal fun shouldReplaceProgressSnapshotEntry(
|
||||
existing: WatchProgressEntry,
|
||||
candidate: WatchProgressEntry,
|
||||
): Boolean {
|
||||
val normalizedExisting = existing.normalizedCompletion()
|
||||
val normalizedCandidate = candidate.normalizedCompletion()
|
||||
val existingInProgress = normalizedExisting.shouldTreatAsInProgressForContinueWatching()
|
||||
val candidateInProgress = normalizedCandidate.shouldTreatAsInProgressForContinueWatching()
|
||||
if (existingInProgress != candidateInProgress) {
|
||||
val inProgressEntry = if (candidateInProgress) normalizedCandidate else normalizedExisting
|
||||
val completedEntry = if (candidateInProgress) normalizedExisting else normalizedCandidate
|
||||
val inProgressIsCurrentEnough =
|
||||
inProgressEntry.lastUpdatedEpochMs >= completedEntry.lastUpdatedEpochMs - WatchProgressSnapshotConflictToleranceMs
|
||||
return if (candidateInProgress) inProgressIsCurrentEnough else !inProgressIsCurrentEnough
|
||||
}
|
||||
return normalizedCandidate.lastUpdatedEpochMs > normalizedExisting.lastUpdatedEpochMs
|
||||
}
|
||||
|
||||
internal fun shouldCascadeCompletedProgressToWatchedHistory(
|
||||
entry: WatchProgressEntry,
|
||||
isUsingTraktProgress: Boolean,
|
||||
|
|
|
|||
|
|
@ -191,6 +191,76 @@ class WatchProgressRulesTest {
|
|||
assertFalse(history.shouldTreatAsInProgressForContinueWatching())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Trakt playback does not replace watched history when watched timestamp is newer`() {
|
||||
val watched = entry(
|
||||
videoId = "show:1:4",
|
||||
parentMetaId = "show",
|
||||
seasonNumber = 1,
|
||||
episodeNumber = 4,
|
||||
lastUpdatedEpochMs = 3_000L,
|
||||
isCompleted = true,
|
||||
progressPercent = 100f,
|
||||
source = WatchProgressSourceTraktHistory,
|
||||
)
|
||||
val playback = watched.copy(
|
||||
lastUpdatedEpochMs = 1_000L,
|
||||
isCompleted = false,
|
||||
progressPercent = 25f,
|
||||
source = WatchProgressSourceTraktPlayback,
|
||||
)
|
||||
|
||||
assertFalse(shouldReplaceProgressSnapshotEntry(existing = watched, candidate = playback))
|
||||
assertTrue(shouldReplaceProgressSnapshotEntry(existing = playback, candidate = watched))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Trakt playback replaces watched history when playback timestamp is newer`() {
|
||||
val watched = entry(
|
||||
videoId = "show:1:4",
|
||||
parentMetaId = "show",
|
||||
seasonNumber = 1,
|
||||
episodeNumber = 4,
|
||||
lastUpdatedEpochMs = 1_000L,
|
||||
isCompleted = true,
|
||||
progressPercent = 100f,
|
||||
source = WatchProgressSourceTraktHistory,
|
||||
)
|
||||
val playback = watched.copy(
|
||||
lastUpdatedEpochMs = 3_000L,
|
||||
isCompleted = false,
|
||||
progressPercent = 25f,
|
||||
source = WatchProgressSourceTraktPlayback,
|
||||
)
|
||||
|
||||
assertTrue(shouldReplaceProgressSnapshotEntry(existing = watched, candidate = playback))
|
||||
assertFalse(shouldReplaceProgressSnapshotEntry(existing = playback, candidate = watched))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `Trakt playback uses TV timestamp tolerance against watched history`() {
|
||||
val watched = entry(
|
||||
videoId = "show:1:4",
|
||||
parentMetaId = "show",
|
||||
seasonNumber = 1,
|
||||
episodeNumber = 4,
|
||||
lastUpdatedEpochMs = 2_000L,
|
||||
isCompleted = true,
|
||||
progressPercent = 100f,
|
||||
source = WatchProgressSourceTraktHistory,
|
||||
)
|
||||
val insideTolerance = watched.copy(
|
||||
lastUpdatedEpochMs = 1_001L,
|
||||
isCompleted = false,
|
||||
progressPercent = 25f,
|
||||
source = WatchProgressSourceTraktPlayback,
|
||||
)
|
||||
val outsideTolerance = insideTolerance.copy(lastUpdatedEpochMs = 999L)
|
||||
|
||||
assertTrue(shouldReplaceProgressSnapshotEntry(existing = watched, candidate = insideTolerance))
|
||||
assertFalse(shouldReplaceProgressSnapshotEntry(existing = watched, candidate = outsideTolerance))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `completed progress does not cascade to watched history while Trakt progress is active`() {
|
||||
val completed = entry(
|
||||
|
|
|
|||
Loading…
Reference in a new issue