mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
refactor(data/jellyfin): reload media items on user data change events
This commit is contained in:
@@ -4,6 +4,7 @@ import hu.bbara.purefin.core.data.LocalMediaRepository
|
||||
import hu.bbara.purefin.core.data.NetworkMonitor
|
||||
import hu.bbara.purefin.core.data.UserSessionRepository
|
||||
import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
|
||||
import hu.bbara.purefin.model.Media
|
||||
import kotlinx.coroutines.CancellationException
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -21,19 +22,7 @@ import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
import javax.inject.Singleton
|
||||
|
||||
/**
|
||||
* Subscribes to the Jellyfin server's [UserDataChangedMessage] WebSocket event
|
||||
* and propagates the changes to the local media repository so the UI updates
|
||||
* the affected item in place.
|
||||
*
|
||||
* The WebSocket follows the lifecycle of the [JellyfinApiClient]'s [ApiClient][org.jellyfin.sdk.api.client.ApiClient]:
|
||||
* the SDK automatically reconnects when the server URL, client info, device
|
||||
* info or access token change (see [org.jellyfin.sdk.api.sockets.SocketApi]).
|
||||
*
|
||||
* The subscription is only active while the user is logged in and the device
|
||||
* is online, matching the gating used by other long-running background work
|
||||
* such as [hu.bbara.purefin.data.jellyfin.playback.SyncPlaybackPositionsHomeRefreshSideEffect].
|
||||
*/
|
||||
|
||||
@Singleton
|
||||
class JellyfinWebSocketService @Inject constructor(
|
||||
private val jellyfinApiClient: JellyfinApiClient,
|
||||
@@ -55,10 +44,6 @@ class JellyfinWebSocketService @Inject constructor(
|
||||
// in-flight subscription instead of leaving it running.
|
||||
.collectLatest { active ->
|
||||
if (!active) return@collectLatest
|
||||
// Re-subscribe in a loop so a transient failure (e.g. the
|
||||
// first subscription attempt throws because the access
|
||||
// token is still being applied) does not permanently
|
||||
// silence the service.
|
||||
while (currentCoroutineContext().isActive) {
|
||||
try {
|
||||
listenForUserDataChanges()
|
||||
@@ -68,7 +53,7 @@ class JellyfinWebSocketService @Inject constructor(
|
||||
Timber.tag(TAG).w(error, "UserDataChanged subscription ended, retrying")
|
||||
}
|
||||
if (!currentCoroutineContext().isActive) break
|
||||
delay(RETRY_DELAY_MS)
|
||||
delay(5000L)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -80,25 +65,26 @@ class JellyfinWebSocketService @Inject constructor(
|
||||
.collect { message ->
|
||||
val info = message.data ?: return@collect
|
||||
for (entry in info.userDataList) {
|
||||
val itemId = entry.itemId ?: continue
|
||||
// updateWatchProgressPercent sets both `progress` and a
|
||||
// percent-derived `watched` (>= 90 % rule, see
|
||||
// InMemoryLocalMediaRepository.updateWatchProgressPercent).
|
||||
// The follow-up markAsWatched is needed so the server's
|
||||
// explicit `played` flag wins over the percent-derived
|
||||
// boolean when they disagree (e.g. a stale "100 %" entry
|
||||
// with played = false on an unmark), and so we set
|
||||
// `watched = true` for entries that only carry `played`.
|
||||
entry.playedPercentage
|
||||
?.takeUnless { it.isNaN() }
|
||||
?.let { localMediaRepository.updateWatchProgressPercent(itemId, it) }
|
||||
localMediaRepository.markAsWatched(itemId, entry.played)
|
||||
val itemId = entry.itemId
|
||||
localMediaRepository.getTypeById(itemId).let { media ->
|
||||
when (media) {
|
||||
is Media.MovieMedia -> {
|
||||
localMediaRepository.loadMovie(media.id)
|
||||
}
|
||||
is Media.EpisodeMedia -> {
|
||||
localMediaRepository.loadEpisode(media.id)
|
||||
}
|
||||
is Media.SeriesMedia -> {
|
||||
localMediaRepository.loadSeries(media.id)
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private companion object {
|
||||
const val TAG = "JellyfinWebSocket"
|
||||
const val RETRY_DELAY_MS = 5_000L
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user