feat: add preferenceMediaId to PlayableMedia and update related logic to make more prone to mistakes

This commit is contained in:
2026-05-13 22:52:49 +02:00
parent 9fb3672c19
commit cc643ae34f
3 changed files with 41 additions and 20 deletions

View File

@@ -5,6 +5,7 @@ import java.util.UUID
sealed class PlayableMedia {
abstract val id: UUID
abstract val preferenceMediaId: UUID
abstract val resumePositionMs: Long
abstract val mediaItem: MediaItem
abstract val preferences: MediaTrackPreferences
@@ -12,6 +13,7 @@ sealed class PlayableMedia {
data class Movie(
override val id: UUID,
override val preferenceMediaId: UUID,
override val resumePositionMs: Long,
override val mediaItem: MediaItem,
override val preferences: MediaTrackPreferences,
@@ -20,6 +22,7 @@ sealed class PlayableMedia {
data class Series(
override val id: UUID,
override val preferenceMediaId: UUID,
override val resumePositionMs: Long,
override val mediaItem: MediaItem,
override val preferences: MediaTrackPreferences,
@@ -28,6 +31,7 @@ sealed class PlayableMedia {
data class Episode(
override val id: UUID,
override val preferenceMediaId: UUID,
override val resumePositionMs: Long,
override val mediaItem: MediaItem,
override val preferences: MediaTrackPreferences,

View File

@@ -11,7 +11,6 @@ import androidx.media3.exoplayer.ExoPlayer
import dagger.hilt.android.scopes.ViewModelScoped
import hu.bbara.purefin.core.data.PlayableMediaRepository
import hu.bbara.purefin.core.data.PlaybackReportContext
import hu.bbara.purefin.core.feature.content.episode.SeriesIdLookUpUseCase
import hu.bbara.purefin.core.player.model.MetadataState
import hu.bbara.purefin.core.player.model.PlaybackProgressSnapshot
import hu.bbara.purefin.core.player.model.PlaybackStateSnapshot
@@ -56,7 +55,6 @@ class PlayerManager @Inject constructor(
private val playableMediaRepository: PlayableMediaRepository,
private val trackPreferencesRepository: TrackPreferencesRepository,
private val trackMatcher: TrackMatcher,
private val seriesIdLookUpUseCase: SeriesIdLookUpUseCase,
private val settingsRepository: SettingsRepository
) {
companion object {
@@ -116,7 +114,8 @@ class PlayerManager @Inject constructor(
override fun onMediaItemTransition(mediaItem: MediaItem?, reason: Int) {
clearActiveSkippableSegment()
_currentMediaId.value = mediaItem?.mediaId?.let { UUID.fromString(it) }
val mediaId = mediaItem?.mediaId?.let { UUID.fromString(it) }
_currentMediaId.value = mediaId
scope.launch {
val currentMedia = _playlist.value.firstOrNull { it.id == _currentMediaId.value }
if (currentMedia == null) {
@@ -263,6 +262,15 @@ class PlayerManager @Inject constructor(
}
fun selectTrack(option: TrackOption) {
scope.launch {
if (option.type != TrackType.VIDEO) {
saveTrackPreference(option)
}
applyTrackSelection(option)
}
}
private fun applyTrackSelection(option: TrackOption) {
val builder = player.trackSelectionParameters.buildUpon()
when (option.type) {
TrackType.TEXT -> {
@@ -296,13 +304,6 @@ class PlayerManager @Inject constructor(
}
}
player.trackSelectionParameters = builder.build()
// Save track preference if media id is available
_currentMediaId.value?.let { mediaId ->
scope.launch {
saveTrackPreference(option, mediaId)
}
}
}
private fun installMediaSegments(mediaSegments: List<MediaSegment>) {
@@ -329,9 +330,14 @@ class PlayerManager @Inject constructor(
}
private suspend fun applyTrackPreferences() {
val preferences = currentPlayableMedia.firstOrNull()?.preferences ?: return
val currentMedia = currentPlayableMedia.firstOrNull() ?: return
val currentTrackState = _tracks.value
if (currentTrackState.audioTracks.isEmpty() && currentTrackState.textTracks.isEmpty()) return
val preferences = trackPreferencesRepository
.getMediaPreferences(currentMedia.preferenceMediaId.toString())
.firstOrNull()
?: return
// Apply audio preference
preferences.audioPreference?.let { audioPreference ->
@@ -339,7 +345,9 @@ class PlayerManager @Inject constructor(
currentTrackState.audioTracks,
audioPreference
)
matchedAudio?.let { selectTrack(it) }
if (matchedAudio != null && matchedAudio.id != currentTrackState.selectedAudioTrackId) {
applyTrackSelection(matchedAudio)
}
}
// Apply subtitle preference
@@ -348,15 +356,17 @@ class PlayerManager @Inject constructor(
currentTrackState.textTracks,
subtitlePreference
)
matchedSubtitle?.let { selectTrack(it) }
if (matchedSubtitle != null && matchedSubtitle.id != currentTrackState.selectedTextTrackId) {
applyTrackSelection(matchedSubtitle)
}
}
}
private suspend fun saveTrackPreference(option: TrackOption, mediaId: UUID) {
val preferenceMediaId = when (currentPlayableMedia.firstOrNull()) {
is PlayableMedia.Episode -> seriesIdLookUpUseCase(mediaId) ?: mediaId
else -> mediaId
}.toString()
private suspend fun saveTrackPreference(option: TrackOption) {
val preferenceMediaId = currentPlayableMedia.firstOrNull()
?.preferenceMediaId
?.toString()
?: return
when (option.type) {
TrackType.AUDIO -> {

View File

@@ -48,11 +48,16 @@ class DefaultPlayableMediaRepository @Inject constructor(
val mediaItem = getMediaItem(baseItem, playbackDecision)
val resumePositionMs = calculateResumePosition(baseItem, playbackDecision.mediaSource)
val mediaTrackPreferences = trackPreferencesRepository.getMediaPreferences(baseItem.parentId.toString()).first()
val preferenceMediaId = when (baseItem.type) {
BaseItemKind.EPISODE -> baseItem.seriesId ?: mediaId
else -> mediaId
}
val mediaTrackPreferences = trackPreferencesRepository.getMediaPreferences(preferenceMediaId.toString()).first()
val mediaSegments = getMediaSegments(mediaId)
when (baseItem.type) {
BaseItemKind.MOVIE -> PlayableMedia.Movie(
id = mediaId,
preferenceMediaId = preferenceMediaId,
mediaItem = mediaItem,
resumePositionMs = resumePositionMs ?: 0L,
preferences = mediaTrackPreferences,
@@ -60,6 +65,7 @@ class DefaultPlayableMediaRepository @Inject constructor(
)
BaseItemKind.SERIES -> PlayableMedia.Series(
id = mediaId,
preferenceMediaId = preferenceMediaId,
mediaItem = mediaItem,
resumePositionMs = resumePositionMs ?: 0L,
preferences = mediaTrackPreferences,
@@ -67,6 +73,7 @@ class DefaultPlayableMediaRepository @Inject constructor(
)
BaseItemKind.EPISODE -> PlayableMedia.Episode(
id = mediaId,
preferenceMediaId = preferenceMediaId,
mediaItem = mediaItem,
resumePositionMs = resumePositionMs ?: 0L,
preferences = mediaTrackPreferences,