refactor(media): consolidate metadata update functions into MediaMetadataUpdater

Replace the disparate JellyfinMediaMetadataUpdater, LocalMediaUpdater,
and direct API/repository calls for watched status and progress updates
with a single unified MediaMetadataUpdater interface and implementation.

The new implementation coordinates both local cache (in-memory/Room)
and remote server updates, so callers have a single point of entry
for all metadata mutations. markAsWatched now updates both server
and local state, fixing a gap where the UI would not reflect
watched changes until a full refresh.
This commit is contained in:
2026-06-12 18:08:32 +00:00
parent def92ad111
commit e78a3700a6
11 changed files with 90 additions and 39 deletions

View File

@@ -1,13 +1,17 @@
package hu.bbara.purefin.data.jellyfin
import hu.bbara.purefin.core.data.LocalMediaRepository
import hu.bbara.purefin.core.data.MediaMetadataUpdater
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
import hu.bbara.purefin.core.jellyfin.JellyfinMediaMetadataUpdater
import java.util.UUID
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class JellyfinMediaMetadataUpdaterImpl @Inject constructor(
private val jellyfinApiClient: JellyfinApiClient
) : JellyfinMediaMetadataUpdater {
private val jellyfinApiClient: JellyfinApiClient,
private val localMediaRepository: LocalMediaRepository,
) : MediaMetadataUpdater {
override suspend fun markAsWatched(mediaId: UUID, watched: Boolean) {
if (watched) {
@@ -15,5 +19,22 @@ class JellyfinMediaMetadataUpdaterImpl @Inject constructor(
} else {
jellyfinApiClient.markAsUnwatched(mediaId)
}
localMediaRepository.markAsWatched(mediaId, watched)
}
}
override suspend fun updateWatchProgress(mediaId: UUID, positionMs: Long, durationMs: Long) {
localMediaRepository.updateWatchProgress(mediaId, positionMs, durationMs)
}
override suspend fun updateWatchProgressPercent(mediaId: UUID, progressPercent: Double) {
localMediaRepository.updateWatchProgressPercent(mediaId, progressPercent)
}
override suspend fun updatePlaybackPosition(
mediaId: UUID,
playbackPositionTicks: Long,
runtimeTicks: Long,
) {
jellyfinApiClient.updatePlaybackPosition(mediaId, playbackPositionTicks, runtimeTicks)
}
}

View File

@@ -3,6 +3,7 @@ package hu.bbara.purefin.data.jellyfin.playback
import hu.bbara.purefin.core.Offline
import hu.bbara.purefin.core.Online
import hu.bbara.purefin.core.data.LocalMediaRepository
import hu.bbara.purefin.core.data.MediaMetadataUpdater
import hu.bbara.purefin.core.data.NetworkMonitor
import hu.bbara.purefin.core.feature.browse.home.refresh.HomeRefreshSideEffect
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
@@ -19,6 +20,7 @@ import kotlin.math.roundToLong
class SyncPlaybackPositionsHomeRefreshSideEffect @Inject constructor(
private val networkMonitor: NetworkMonitor,
private val jellyfinApiClient: JellyfinApiClient,
private val mediaMetadataUpdater: MediaMetadataUpdater,
@param:Offline private val offlineRepository: LocalMediaRepository,
@param:Online private val onlineRepository: LocalMediaRepository,
) : HomeRefreshSideEffect {
@@ -49,12 +51,12 @@ class SyncPlaybackPositionsHomeRefreshSideEffect @Inject constructor(
// furthest known playback position as the best available source of truth.
when {
localPlaybackPositionTicks > remotePlaybackPosition.playbackPositionTicks + tickTolerance -> {
jellyfinApiClient.updatePlaybackPosition(
mediaMetadataUpdater.updatePlaybackPosition(
mediaId = localPlaybackPosition.mediaId,
playbackPositionTicks = localPlaybackPositionTicks,
runtimeTicks = remotePlaybackPosition.runtimeTicks,
)
onlineRepository.updateWatchProgressPercent(
mediaMetadataUpdater.updateWatchProgressPercent(
mediaId = localPlaybackPosition.mediaId,
progressPercent = localPlaybackPositionTicks.toProgressPercent(
runtimeTicks = remotePlaybackPosition.runtimeTicks,
@@ -65,11 +67,7 @@ class SyncPlaybackPositionsHomeRefreshSideEffect @Inject constructor(
val remoteProgressPercent = remotePlaybackPosition.playbackPositionTicks.toProgressPercent(
runtimeTicks = remotePlaybackPosition.runtimeTicks,
)
offlineRepository.updateWatchProgressPercent(
mediaId = localPlaybackPosition.mediaId,
progressPercent = remoteProgressPercent,
)
onlineRepository.updateWatchProgressPercent(
mediaMetadataUpdater.updateWatchProgressPercent(
mediaId = localPlaybackPosition.mediaId,
progressPercent = remoteProgressPercent,
)

View File

@@ -14,7 +14,7 @@ import hu.bbara.purefin.data.catalog.InMemoryLocalMediaRepository
import hu.bbara.purefin.data.catalog.OfflineLocalMediaRepository
import hu.bbara.purefin.data.jellyfin.JellyfinMediaMetadataUpdaterImpl
import hu.bbara.purefin.data.jellyfin.SearchManagerImpl
import hu.bbara.purefin.core.jellyfin.JellyfinMediaMetadataUpdater
import hu.bbara.purefin.core.data.MediaMetadataUpdater
@Module
@InstallIn(SingletonComponent::class)
@@ -32,7 +32,7 @@ abstract class MediaRepositoryModule {
abstract fun bindHomeRepository(impl: InMemoryAppContentRepository): HomeRepository
@Binds
abstract fun bindJellyfinMediaMetadataUpdater(impl: JellyfinMediaMetadataUpdaterImpl): JellyfinMediaMetadataUpdater
abstract fun bindMediaMetadataUpdater(impl: JellyfinMediaMetadataUpdaterImpl): MediaMetadataUpdater
@Binds
abstract fun bindSearchManager(impl: SearchManagerImpl): SearchManager