mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-23 19:26:50 +00:00
refactor: Enhance error handling in API calls with logging
This commit is contained in:
@@ -11,6 +11,7 @@ import hu.bbara.purefin.data.jellyfin.client.JellyfinApiClient
|
|||||||
import hu.bbara.purefin.model.Episode
|
import hu.bbara.purefin.model.Episode
|
||||||
import hu.bbara.purefin.model.Movie
|
import hu.bbara.purefin.model.Movie
|
||||||
import hu.bbara.purefin.model.Series
|
import hu.bbara.purefin.model.Series
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
@@ -105,7 +106,14 @@ class InMemoryMediaRepository @Inject constructor(
|
|||||||
|
|
||||||
override fun observeSeriesWithContent(seriesId: UUID): Flow<Series?> {
|
override fun observeSeriesWithContent(seriesId: UUID): Flow<Series?> {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
try {
|
||||||
ensureSeriesContentLoaded(seriesId)
|
ensureSeriesContentLoaded(seriesId)
|
||||||
|
} catch (error: CancellationException) {
|
||||||
|
throw error
|
||||||
|
} catch (error: Exception) {
|
||||||
|
Log.e("InMemoryMediaRepository", "Failed to load content for series $seriesId", error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return seriesState.map { it[seriesId] }
|
return seriesState.map { it[seriesId] }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import dagger.hilt.android.qualifiers.ApplicationContext
|
|||||||
import hu.bbara.purefin.data.PlaybackMethod
|
import hu.bbara.purefin.data.PlaybackMethod
|
||||||
import hu.bbara.purefin.data.PlaybackReportContext
|
import hu.bbara.purefin.data.PlaybackReportContext
|
||||||
import hu.bbara.purefin.data.UserSessionRepository
|
import hu.bbara.purefin.data.UserSessionRepository
|
||||||
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.first
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -85,26 +86,31 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun configureFromSession(): Boolean = withContext(Dispatchers.IO) {
|
suspend fun configureFromSession(): Boolean = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("configureFromSession") {
|
||||||
ensureConfigured()
|
ensureConfigured()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun authenticate(
|
suspend fun authenticate(
|
||||||
url: String,
|
url: String,
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
): AuthenticationResult? = withContext(Dispatchers.IO) {
|
): AuthenticationResult? = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("authenticate") {
|
||||||
val trimmedUrl = url.trim()
|
val trimmedUrl = url.trim()
|
||||||
if (trimmedUrl.isBlank()) {
|
if (trimmedUrl.isBlank()) {
|
||||||
return@withContext null
|
return@logApiFailure null
|
||||||
}
|
}
|
||||||
|
|
||||||
api.update(baseUrl = trimmedUrl)
|
api.update(baseUrl = trimmedUrl)
|
||||||
api.userApi.authenticateUserByName(username = username, password = password).content
|
api.userApi.authenticateUserByName(username = username, password = password).content
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getLibraries(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getLibraries(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getLibraries") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val response = api.userViewsApi.getUserViews(
|
val response = api.userViewsApi.getUserViews(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -114,10 +120,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getLibraries", response.content.toString())
|
Log.d("getLibraries", response.content.toString())
|
||||||
response.content.items
|
response.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getLibraryContent(libraryId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getLibraryContent(libraryId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getLibraryContent($libraryId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val getItemsRequest = GetItemsRequest(
|
val getItemsRequest = GetItemsRequest(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -132,12 +140,14 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getLibraryContent", response.content.toString())
|
Log.d("getLibraryContent", response.content.toString())
|
||||||
response.content.items
|
response.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getSuggestions(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getSuggestions(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getSuggestions") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val userId = getUserId() ?: return@withContext emptyList()
|
val userId = getUserId() ?: return@logApiFailure emptyList()
|
||||||
val response = api.suggestionsApi.getSuggestions(
|
val response = api.suggestionsApi.getSuggestions(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
mediaType = listOf(MediaType.VIDEO),
|
mediaType = listOf(MediaType.VIDEO),
|
||||||
@@ -148,12 +158,14 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getSuggestions", response.content.toString())
|
Log.d("getSuggestions", response.content.toString())
|
||||||
response.content.items
|
response.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getContinueWatching(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getContinueWatching(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getContinueWatching") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val userId = getUserId() ?: return@withContext emptyList()
|
val userId = getUserId() ?: return@logApiFailure emptyList()
|
||||||
val getResumeItemsRequest = GetResumeItemsRequest(
|
val getResumeItemsRequest = GetResumeItemsRequest(
|
||||||
userId = userId,
|
userId = userId,
|
||||||
fields = itemFields,
|
fields = itemFields,
|
||||||
@@ -165,8 +177,10 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getContinueWatching", response.content.toString())
|
Log.d("getContinueWatching", response.content.toString())
|
||||||
response.content.items
|
response.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getNextUpEpisodes(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getNextUpEpisodes(): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getNextUpEpisodes") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
throw IllegalStateException("Not configured")
|
throw IllegalStateException("Not configured")
|
||||||
}
|
}
|
||||||
@@ -179,10 +193,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getNextUpEpisodes", result.content.toString())
|
Log.d("getNextUpEpisodes", result.content.toString())
|
||||||
result.content.items
|
result.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getLatestFromLibrary(libraryId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getLatestFromLibrary(libraryId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getLatestFromLibrary($libraryId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val response = api.userLibraryApi.getLatestMedia(
|
val response = api.userLibraryApi.getLatestMedia(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -194,19 +210,23 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getLatestFromLibrary", response.content.toString())
|
Log.d("getLatestFromLibrary", response.content.toString())
|
||||||
response.content
|
response.content
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getItemInfo(mediaId: UUID): BaseItemDto? = withContext(Dispatchers.IO) {
|
suspend fun getItemInfo(mediaId: UUID): BaseItemDto? = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getItemInfo($mediaId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext null
|
return@logApiFailure null
|
||||||
}
|
}
|
||||||
val result = api.userLibraryApi.getItem(itemId = mediaId, userId = getUserId())
|
val result = api.userLibraryApi.getItem(itemId = mediaId, userId = getUserId())
|
||||||
Log.d("getItemInfo", result.content.toString())
|
Log.d("getItemInfo", result.content.toString())
|
||||||
result.content
|
result.content
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getSeasons(seriesId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getSeasons(seriesId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getSeasons($seriesId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val result = api.tvShowsApi.getSeasons(
|
val result = api.tvShowsApi.getSeasons(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -217,10 +237,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getSeasons", result.content.toString())
|
Log.d("getSeasons", result.content.toString())
|
||||||
result.content.items
|
result.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getEpisodesInSeason(seriesId: UUID, seasonId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getEpisodesInSeason(seriesId: UUID, seasonId: UUID): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getEpisodesInSeason(series=$seriesId, season=$seasonId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val result = api.tvShowsApi.getEpisodes(
|
val result = api.tvShowsApi.getEpisodes(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -232,13 +254,15 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getEpisodesInSeason", result.content.toString())
|
Log.d("getEpisodesInSeason", result.content.toString())
|
||||||
result.content.items
|
result.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getNextEpisodes(episodeId: UUID, count: Int): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getNextEpisodes(episodeId: UUID, count: Int): List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getNextEpisodes($episodeId, count=$count)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val episodeInfo = getItemInfo(episodeId) ?: return@withContext emptyList()
|
val episodeInfo = getItemInfo(episodeId) ?: return@logApiFailure emptyList()
|
||||||
val seriesId = episodeInfo.seriesId ?: return@withContext emptyList()
|
val seriesId = episodeInfo.seriesId ?: return@logApiFailure emptyList()
|
||||||
val nextUpEpisodesResult = api.tvShowsApi.getEpisodes(
|
val nextUpEpisodesResult = api.tvShowsApi.getEpisodes(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
seriesId = seriesId,
|
seriesId = seriesId,
|
||||||
@@ -250,10 +274,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getNextEpisodes", nextUpEpisodes.toString())
|
Log.d("getNextEpisodes", nextUpEpisodes.toString())
|
||||||
nextUpEpisodes
|
nextUpEpisodes
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getGenres(id: UUID? = null) : List<BaseItemDto> = withContext(Dispatchers.IO) {
|
suspend fun getGenres(id: UUID? = null) : List<BaseItemDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getGenres($id)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val result = api.genresApi.getGenres(
|
val result = api.genresApi.getGenres(
|
||||||
userId = getUserId(),
|
userId = getUserId(),
|
||||||
@@ -262,10 +288,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getGenres", result.toString())
|
Log.d("getGenres", result.toString())
|
||||||
result.content.items
|
result.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getMediaSources(mediaId: UUID): List<MediaSourceInfo> = withContext(Dispatchers.IO) {
|
suspend fun getMediaSources(mediaId: UUID): List<MediaSourceInfo> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getMediaSources($mediaId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val result = api.mediaInfoApi.getPostedPlaybackInfo(
|
val result = api.mediaInfoApi.getPostedPlaybackInfo(
|
||||||
mediaId,
|
mediaId,
|
||||||
@@ -278,10 +306,12 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getMediaSources", result.toString())
|
Log.d("getMediaSources", result.toString())
|
||||||
result.content.mediaSources
|
result.content.mediaSources
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getMediaSegments(mediaId: UUID) : List<MediaSegmentDto> = withContext(Dispatchers.IO) {
|
suspend fun getMediaSegments(mediaId: UUID) : List<MediaSegmentDto> = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getMediaSegments($mediaId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext emptyList()
|
return@logApiFailure emptyList()
|
||||||
}
|
}
|
||||||
val result = api.mediaSegmentsApi.getItemSegments(
|
val result = api.mediaSegmentsApi.getItemSegments(
|
||||||
itemId = mediaId,
|
itemId = mediaId,
|
||||||
@@ -290,13 +320,15 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
Log.d("getMediaSegments", result.toString())
|
Log.d("getMediaSegments", result.toString())
|
||||||
result.content.items
|
result.content.items
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getPlaybackInfo(
|
suspend fun getPlaybackInfo(
|
||||||
mediaId: UUID,
|
mediaId: UUID,
|
||||||
deviceProfile: DeviceProfile,
|
deviceProfile: DeviceProfile,
|
||||||
): PlaybackInfoResponse? = withContext(Dispatchers.IO) {
|
): PlaybackInfoResponse? = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getPlaybackInfo($mediaId)") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext null
|
return@logApiFailure null
|
||||||
}
|
}
|
||||||
api.mediaInfoApi.getPostedPlaybackInfo(
|
api.mediaInfoApi.getPostedPlaybackInfo(
|
||||||
mediaId,
|
mediaId,
|
||||||
@@ -312,6 +344,7 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
),
|
),
|
||||||
).content
|
).content
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun getVideoStreamUrl(
|
fun getVideoStreamUrl(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
@@ -320,7 +353,8 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
tag: String? = null,
|
tag: String? = null,
|
||||||
playSessionId: String? = null,
|
playSessionId: String? = null,
|
||||||
liveStreamId: String? = null,
|
liveStreamId: String? = null,
|
||||||
): String = api.videosApi.getVideoStreamUrl(
|
): String = try {
|
||||||
|
api.videosApi.getVideoStreamUrl(
|
||||||
itemId = itemId,
|
itemId = itemId,
|
||||||
container = container,
|
container = container,
|
||||||
mediaSourceId = mediaSourceId,
|
mediaSourceId = mediaSourceId,
|
||||||
@@ -329,20 +363,27 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
playSessionId = playSessionId,
|
playSessionId = playSessionId,
|
||||||
liveStreamId = liveStreamId,
|
liveStreamId = liveStreamId,
|
||||||
)
|
)
|
||||||
|
} catch (error: Exception) {
|
||||||
|
Log.e(TAG, "getVideoStreamUrl($itemId) failed", error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun getPublicSystemInfoVersion(): String? = withContext(Dispatchers.IO) {
|
suspend fun getPublicSystemInfoVersion(): String? = withContext(Dispatchers.IO) {
|
||||||
|
logApiFailure("getPublicSystemInfoVersion") {
|
||||||
if (!ensureConfigured()) {
|
if (!ensureConfigured()) {
|
||||||
return@withContext null
|
return@logApiFailure null
|
||||||
}
|
}
|
||||||
SystemApi(api).getPublicSystemInfo().content.version
|
SystemApi(api).getPublicSystemInfo().content.version
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun reportPlaybackStart(
|
suspend fun reportPlaybackStart(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
positionTicks: Long = 0L,
|
positionTicks: Long = 0L,
|
||||||
reportContext: PlaybackReportContext,
|
reportContext: PlaybackReportContext,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
if (!ensureConfigured()) return@withContext
|
logApiFailure("reportPlaybackStart($itemId)") {
|
||||||
|
if (!ensureConfigured()) return@logApiFailure
|
||||||
api.playStateApi.reportPlaybackStart(
|
api.playStateApi.reportPlaybackStart(
|
||||||
PlaybackStartInfo(
|
PlaybackStartInfo(
|
||||||
itemId = itemId,
|
itemId = itemId,
|
||||||
@@ -361,6 +402,7 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun reportPlaybackProgress(
|
suspend fun reportPlaybackProgress(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
@@ -368,7 +410,8 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
isPaused: Boolean,
|
isPaused: Boolean,
|
||||||
reportContext: PlaybackReportContext,
|
reportContext: PlaybackReportContext,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
if (!ensureConfigured()) return@withContext
|
logApiFailure("reportPlaybackProgress($itemId)") {
|
||||||
|
if (!ensureConfigured()) return@logApiFailure
|
||||||
api.playStateApi.reportPlaybackProgress(
|
api.playStateApi.reportPlaybackProgress(
|
||||||
PlaybackProgressInfo(
|
PlaybackProgressInfo(
|
||||||
itemId = itemId,
|
itemId = itemId,
|
||||||
@@ -387,13 +430,15 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun reportPlaybackStopped(
|
suspend fun reportPlaybackStopped(
|
||||||
itemId: UUID,
|
itemId: UUID,
|
||||||
positionTicks: Long,
|
positionTicks: Long,
|
||||||
reportContext: PlaybackReportContext,
|
reportContext: PlaybackReportContext,
|
||||||
) = withContext(Dispatchers.IO) {
|
) = withContext(Dispatchers.IO) {
|
||||||
if (!ensureConfigured()) return@withContext
|
logApiFailure("reportPlaybackStopped($itemId)") {
|
||||||
|
if (!ensureConfigured()) return@logApiFailure
|
||||||
api.playStateApi.reportPlaybackStopped(
|
api.playStateApi.reportPlaybackStopped(
|
||||||
PlaybackStopInfo(
|
PlaybackStopInfo(
|
||||||
itemId = itemId,
|
itemId = itemId,
|
||||||
@@ -405,10 +450,26 @@ class JellyfinApiClient @Inject constructor(
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun <T> logApiFailure(operation: String, block: suspend () -> T): T {
|
||||||
|
return try {
|
||||||
|
block()
|
||||||
|
} catch (error: CancellationException) {
|
||||||
|
throw error
|
||||||
|
} catch (error: Exception) {
|
||||||
|
Log.e(TAG, "$operation failed", error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun PlaybackMethod.toJellyfinPlayMethod(): PlayMethod = when (this) {
|
private fun PlaybackMethod.toJellyfinPlayMethod(): PlayMethod = when (this) {
|
||||||
PlaybackMethod.DIRECT_PLAY -> PlayMethod.DIRECT_PLAY
|
PlaybackMethod.DIRECT_PLAY -> PlayMethod.DIRECT_PLAY
|
||||||
PlaybackMethod.DIRECT_STREAM -> PlayMethod.DIRECT_STREAM
|
PlaybackMethod.DIRECT_STREAM -> PlayMethod.DIRECT_STREAM
|
||||||
PlaybackMethod.TRANSCODE -> PlayMethod.TRANSCODE
|
PlaybackMethod.TRANSCODE -> PlayMethod.TRANSCODE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val TAG = "JellyfinApiClient"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user