Show PWA source ratings on Discover screens
This commit is contained in:
parent
e92ade99df
commit
15b082ccd8
9 changed files with 53 additions and 131 deletions
|
|
@ -3,8 +3,6 @@
|
||||||
package com.github.damontecres.wholphin.data.model
|
package com.github.damontecres.wholphin.data.model
|
||||||
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieMovieIdRatingsGet200Response
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvTvIdRatingsGet200Response
|
|
||||||
import com.github.damontecres.wholphin.ui.detail.CardGridItem
|
import com.github.damontecres.wholphin.ui.detail.CardGridItem
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.util.LocalDateSerializer
|
import com.github.damontecres.wholphin.util.LocalDateSerializer
|
||||||
|
|
@ -123,20 +121,3 @@ data class DiscoverItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A rating for a discovered item which is usually fetched separately from the item
|
|
||||||
*/
|
|
||||||
data class DiscoverRating(
|
|
||||||
val criticRating: Int?,
|
|
||||||
val audienceRating: Float?,
|
|
||||||
) {
|
|
||||||
constructor(rating: MovieMovieIdRatingsGet200Response) : this(
|
|
||||||
criticRating = rating.criticsScore,
|
|
||||||
audienceRating = rating.audienceScore?.div(10f),
|
|
||||||
)
|
|
||||||
constructor(rating: TvTvIdRatingsGet200Response) : this(
|
|
||||||
criticRating = rating.criticsScore,
|
|
||||||
audienceRating = null,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,12 @@ import android.content.Context
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.text.format.DateFormat
|
import android.text.format.DateFormat
|
||||||
import androidx.annotation.StringRes
|
import androidx.annotation.StringRes
|
||||||
import androidx.compose.foundation.text.appendInlineContent
|
|
||||||
import androidx.compose.ui.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
import androidx.compose.ui.text.buildAnnotatedString
|
import androidx.compose.ui.text.buildAnnotatedString
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.WholphinApplication
|
import com.github.damontecres.wholphin.WholphinApplication
|
||||||
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
|
import com.github.damontecres.wholphin.data.model.appendRatings
|
||||||
import org.jellyfin.sdk.model.api.BaseItemDto
|
import org.jellyfin.sdk.model.api.BaseItemDto
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
import org.jellyfin.sdk.model.api.MediaSegmentType
|
import org.jellyfin.sdk.model.api.MediaSegmentType
|
||||||
|
|
@ -234,27 +235,16 @@ fun AnnotatedString.Builder.dot() = append(" \u2022 ")
|
||||||
|
|
||||||
fun listToDotString(
|
fun listToDotString(
|
||||||
strings: List<String>,
|
strings: List<String>,
|
||||||
communityRating: Float?,
|
ratings: SourceRatings?,
|
||||||
criticRating: Float?,
|
|
||||||
): AnnotatedString =
|
): AnnotatedString =
|
||||||
buildAnnotatedString {
|
buildAnnotatedString {
|
||||||
strings.forEachIndexed { index, string ->
|
strings.forEachIndexed { index, string ->
|
||||||
append(string)
|
append(string)
|
||||||
if (index != strings.lastIndex) dot()
|
if (index != strings.lastIndex) dot()
|
||||||
}
|
}
|
||||||
communityRating?.let {
|
ratings?.let {
|
||||||
dot()
|
appendRatings(it.communityEntries)
|
||||||
append(String.format(Locale.getDefault(), "%.1f", it))
|
appendRatings(it.criticEntries)
|
||||||
appendInlineContent(id = "star")
|
|
||||||
}
|
|
||||||
criticRating?.let {
|
|
||||||
dot()
|
|
||||||
append("${it.toInt()}%")
|
|
||||||
if (it >= 60f) {
|
|
||||||
appendInlineContent(id = "fresh")
|
|
||||||
} else {
|
|
||||||
appendInlineContent(id = "rotten")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
||||||
|
|
@ -185,7 +185,7 @@ fun DiscoverMovieDetailsContent(
|
||||||
preferences: UserPreferences,
|
preferences: UserPreferences,
|
||||||
userConfig: SeerrUserConfig?,
|
userConfig: SeerrUserConfig?,
|
||||||
movie: MovieDetails,
|
movie: MovieDetails,
|
||||||
rating: DiscoverRating?,
|
rating: SourceRatings?,
|
||||||
canCancel: Boolean,
|
canCancel: Boolean,
|
||||||
people: List<DiscoverItem>,
|
people: List<DiscoverItem>,
|
||||||
trailers: List<Trailer>,
|
trailers: List<Trailer>,
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import androidx.tv.material3.MaterialTheme
|
||||||
import androidx.tv.material3.Text
|
import androidx.tv.material3.Text
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.jellyfinId
|
import com.github.damontecres.wholphin.services.jellyfinId
|
||||||
import com.github.damontecres.wholphin.ui.LocalImageUrlService
|
import com.github.damontecres.wholphin.ui.LocalImageUrlService
|
||||||
|
|
@ -44,7 +44,7 @@ import kotlin.time.Duration.Companion.minutes
|
||||||
fun DiscoverMovieDetailsHeader(
|
fun DiscoverMovieDetailsHeader(
|
||||||
preferences: UserPreferences,
|
preferences: UserPreferences,
|
||||||
movie: MovieDetails,
|
movie: MovieDetails,
|
||||||
rating: DiscoverRating?,
|
rating: SourceRatings?,
|
||||||
bringIntoViewRequester: BringIntoViewRequester,
|
bringIntoViewRequester: BringIntoViewRequester,
|
||||||
overviewOnClick: () -> Unit,
|
overviewOnClick: () -> Unit,
|
||||||
showLogo: Boolean,
|
showLogo: Boolean,
|
||||||
|
|
@ -107,8 +107,7 @@ fun DiscoverMovieDetailsHeader(
|
||||||
}.let {
|
}.let {
|
||||||
listToDotString(
|
listToDotString(
|
||||||
it,
|
it,
|
||||||
rating?.audienceRating,
|
rating,
|
||||||
rating?.criticRating?.toFloat(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import com.github.damontecres.wholphin.api.seerr.model.RelatedVideo
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.RequestPostRequest
|
import com.github.damontecres.wholphin.api.seerr.model.RequestPostRequest
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.RequestStatus
|
import com.github.damontecres.wholphin.data.model.RequestStatus
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
||||||
|
|
@ -19,9 +19,11 @@ import com.github.damontecres.wholphin.data.model.Trailer
|
||||||
import com.github.damontecres.wholphin.data.model.hasPermission
|
import com.github.damontecres.wholphin.data.model.hasPermission
|
||||||
import com.github.damontecres.wholphin.services.BackdropService
|
import com.github.damontecres.wholphin.services.BackdropService
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
|
import com.github.damontecres.wholphin.services.SeerrRatingsService
|
||||||
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
||||||
import com.github.damontecres.wholphin.services.SeerrService
|
import com.github.damontecres.wholphin.services.SeerrService
|
||||||
import com.github.damontecres.wholphin.services.SeerrUserConfig
|
import com.github.damontecres.wholphin.services.SeerrUserConfig
|
||||||
|
import com.github.damontecres.wholphin.services.TmdbVote
|
||||||
import com.github.damontecres.wholphin.ui.equalsNotNull
|
import com.github.damontecres.wholphin.ui.equalsNotNull
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.launchDefault
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
|
|
@ -60,6 +62,7 @@ class DiscoverMovieViewModel
|
||||||
private val backdropService: BackdropService,
|
private val backdropService: BackdropService,
|
||||||
val serverRepository: ServerRepository,
|
val serverRepository: ServerRepository,
|
||||||
val seerrService: SeerrService,
|
val seerrService: SeerrService,
|
||||||
|
private val ratingsService: SeerrRatingsService,
|
||||||
private val seerrServerRepository: SeerrServerRepository,
|
private val seerrServerRepository: SeerrServerRepository,
|
||||||
@Assisted val item: DiscoverItem,
|
@Assisted val item: DiscoverItem,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
@ -106,11 +109,11 @@ class DiscoverMovieViewModel
|
||||||
|
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
val rating =
|
val rating =
|
||||||
getDiscoverRating(item.id) {
|
ratingsService.get(
|
||||||
DiscoverRating(
|
SeerrItemType.MOVIE,
|
||||||
seerrService.api.moviesApi.movieMovieIdRatingsGet(movieId = item.id),
|
item.id,
|
||||||
)
|
TmdbVote(movie.voteAverage?.toDouble(), movie.voteCount?.toLong()),
|
||||||
}
|
)
|
||||||
_state.update { it.copy(rating = rating) }
|
_state.update { it.copy(rating = rating) }
|
||||||
}
|
}
|
||||||
if (state.value.similar.isEmpty()) {
|
if (state.value.similar.isEmpty()) {
|
||||||
|
|
@ -276,7 +279,7 @@ fun canUserCancelRequest(
|
||||||
|
|
||||||
data class DiscoverMovieState(
|
data class DiscoverMovieState(
|
||||||
val movie: DataLoadingState<MovieDetails> = DataLoadingState.Pending,
|
val movie: DataLoadingState<MovieDetails> = DataLoadingState.Pending,
|
||||||
val rating: DiscoverRating? = null,
|
val rating: SourceRatings? = null,
|
||||||
val seasons: List<RequestSeason> = emptyList(),
|
val seasons: List<RequestSeason> = emptyList(),
|
||||||
val trailers: List<Trailer> = emptyList(),
|
val trailers: List<Trailer> = emptyList(),
|
||||||
val people: List<DiscoverItem> = emptyList(),
|
val people: List<DiscoverItem> = emptyList(),
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrPermission
|
import com.github.damontecres.wholphin.data.model.SeerrPermission
|
||||||
import com.github.damontecres.wholphin.data.model.Trailer
|
import com.github.damontecres.wholphin.data.model.Trailer
|
||||||
|
|
@ -211,7 +211,7 @@ fun DiscoverSeriesDetailsContent(
|
||||||
preferences: UserPreferences,
|
preferences: UserPreferences,
|
||||||
userConfig: SeerrUserConfig?,
|
userConfig: SeerrUserConfig?,
|
||||||
series: TvDetails,
|
series: TvDetails,
|
||||||
rating: DiscoverRating?,
|
rating: SourceRatings?,
|
||||||
canCancel: Boolean,
|
canCancel: Boolean,
|
||||||
seasons: List<RequestSeason>,
|
seasons: List<RequestSeason>,
|
||||||
similar: List<DiscoverItem>,
|
similar: List<DiscoverItem>,
|
||||||
|
|
@ -422,7 +422,7 @@ fun DiscoverSeriesDetailsContent(
|
||||||
@Composable
|
@Composable
|
||||||
fun DiscoverSeriesDetailsHeader(
|
fun DiscoverSeriesDetailsHeader(
|
||||||
series: TvDetails,
|
series: TvDetails,
|
||||||
rating: DiscoverRating?,
|
rating: SourceRatings?,
|
||||||
overviewOnClick: () -> Unit,
|
overviewOnClick: () -> Unit,
|
||||||
showLogo: Boolean,
|
showLogo: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
|
@ -466,8 +466,7 @@ fun DiscoverSeriesDetailsHeader(
|
||||||
}.let {
|
}.let {
|
||||||
listToDotString(
|
listToDotString(
|
||||||
it,
|
it,
|
||||||
rating?.audienceRating,
|
rating,
|
||||||
rating?.criticRating?.toFloat(),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import com.github.damontecres.wholphin.api.seerr.model.RequestRequestIdPutReques
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
import com.github.damontecres.wholphin.api.seerr.model.TvDetails
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.RequestStatus
|
import com.github.damontecres.wholphin.data.model.RequestStatus
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
import com.github.damontecres.wholphin.data.model.SeerrAvailability
|
||||||
|
|
@ -18,8 +18,10 @@ import com.github.damontecres.wholphin.data.model.SeerrItemType
|
||||||
import com.github.damontecres.wholphin.data.model.Trailer
|
import com.github.damontecres.wholphin.data.model.Trailer
|
||||||
import com.github.damontecres.wholphin.services.BackdropService
|
import com.github.damontecres.wholphin.services.BackdropService
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
|
import com.github.damontecres.wholphin.services.SeerrRatingsService
|
||||||
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
import com.github.damontecres.wholphin.services.SeerrServerRepository
|
||||||
import com.github.damontecres.wholphin.services.SeerrService
|
import com.github.damontecres.wholphin.services.SeerrService
|
||||||
|
import com.github.damontecres.wholphin.services.TmdbVote
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.launchDefault
|
import com.github.damontecres.wholphin.ui.launchDefault
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
|
|
@ -60,6 +62,7 @@ class DiscoverSeriesViewModel
|
||||||
private val backdropService: BackdropService,
|
private val backdropService: BackdropService,
|
||||||
val serverRepository: ServerRepository,
|
val serverRepository: ServerRepository,
|
||||||
val seerrService: SeerrService,
|
val seerrService: SeerrService,
|
||||||
|
private val ratingsService: SeerrRatingsService,
|
||||||
private val seerrServerRepository: SeerrServerRepository,
|
private val seerrServerRepository: SeerrServerRepository,
|
||||||
@Assisted val item: DiscoverItem,
|
@Assisted val item: DiscoverItem,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
@ -109,9 +112,11 @@ class DiscoverSeriesViewModel
|
||||||
|
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
val rating =
|
val rating =
|
||||||
getDiscoverRating(item.id) {
|
ratingsService.get(
|
||||||
DiscoverRating(seerrService.api.tvApi.tvTvIdRatingsGet(tvId = item.id))
|
SeerrItemType.TV,
|
||||||
}
|
item.id,
|
||||||
|
TmdbVote(tv.voteAverage?.toDouble(), tv.voteCount?.toLong()),
|
||||||
|
)
|
||||||
_state.update { it.copy(rating = rating) }
|
_state.update { it.copy(rating = rating) }
|
||||||
}
|
}
|
||||||
if (state.value.similar.isEmpty()) {
|
if (state.value.similar.isEmpty()) {
|
||||||
|
|
@ -416,7 +421,7 @@ class DiscoverSeriesViewModel
|
||||||
|
|
||||||
data class DiscoverSeriesState(
|
data class DiscoverSeriesState(
|
||||||
val tvSeries: DataLoadingState<TvDetails> = DataLoadingState.Pending,
|
val tvSeries: DataLoadingState<TvDetails> = DataLoadingState.Pending,
|
||||||
val rating: DiscoverRating? = null,
|
val rating: SourceRatings? = null,
|
||||||
val seasons: List<RequestSeason> = emptyList(),
|
val seasons: List<RequestSeason> = emptyList(),
|
||||||
val seasons4k: List<RequestSeason> = emptyList(),
|
val seasons4k: List<RequestSeason> = emptyList(),
|
||||||
val trailers: List<Trailer> = emptyList(),
|
val trailers: List<Trailer> = emptyList(),
|
||||||
|
|
|
||||||
|
|
@ -1,39 +1,16 @@
|
||||||
package com.github.damontecres.wholphin.ui.detail.discover
|
package com.github.damontecres.wholphin.ui.detail.discover
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.damontecres.wholphin.api.seerr.infrastructure.ClientException
|
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MediaInfo
|
import com.github.damontecres.wholphin.api.seerr.model.MediaInfo
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
import com.github.damontecres.wholphin.services.jellyfinId
|
import com.github.damontecres.wholphin.services.jellyfinId
|
||||||
import com.github.damontecres.wholphin.services.jellyfinIdAsString
|
import com.github.damontecres.wholphin.services.jellyfinIdAsString
|
||||||
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.showToast
|
import com.github.damontecres.wholphin.ui.showToast
|
||||||
import kotlinx.coroutines.CancellationException
|
|
||||||
import org.jellyfin.sdk.model.api.BaseItemKind
|
import org.jellyfin.sdk.model.api.BaseItemKind
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
|
|
||||||
suspend fun getDiscoverRating(
|
|
||||||
id: Int,
|
|
||||||
func: suspend () -> DiscoverRating,
|
|
||||||
): DiscoverRating? =
|
|
||||||
try {
|
|
||||||
func.invoke()
|
|
||||||
} catch (ex: CancellationException) {
|
|
||||||
throw ex
|
|
||||||
} catch (ex: ClientException) {
|
|
||||||
if (ex.statusCode == 404) {
|
|
||||||
Timber.w("No rating for %s", id)
|
|
||||||
} else {
|
|
||||||
Timber.e(ex, "Error fetching rating for %s", id)
|
|
||||||
}
|
|
||||||
null
|
|
||||||
} catch (ex: Exception) {
|
|
||||||
Timber.e(ex, "Error fetching rating for %s", id)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigates to the Jellyfin media item if the [mediaInfo] has a valid [jellyfinId]
|
* Navigates to the Jellyfin media item if the [mediaInfo] has a valid [jellyfinId]
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -32,17 +32,17 @@ import androidx.lifecycle.viewModelScope
|
||||||
import com.github.damontecres.wholphin.R
|
import com.github.damontecres.wholphin.R
|
||||||
import com.github.damontecres.wholphin.data.filter.DiscoverFilter
|
import com.github.damontecres.wholphin.data.filter.DiscoverFilter
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
|
||||||
import com.github.damontecres.wholphin.data.model.QuickDetailsData
|
import com.github.damontecres.wholphin.data.model.QuickDetailsData
|
||||||
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
||||||
|
import com.github.damontecres.wholphin.data.model.SourceRatings
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.BackdropService
|
import com.github.damontecres.wholphin.services.BackdropService
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
|
import com.github.damontecres.wholphin.services.SeerrRatingsService
|
||||||
import com.github.damontecres.wholphin.services.SeerrService
|
import com.github.damontecres.wholphin.services.SeerrService
|
||||||
import com.github.damontecres.wholphin.ui.components.Genre
|
import com.github.damontecres.wholphin.ui.components.Genre
|
||||||
import com.github.damontecres.wholphin.ui.components.HeaderUtils
|
import com.github.damontecres.wholphin.ui.components.HeaderUtils
|
||||||
import com.github.damontecres.wholphin.ui.data.RowColumn
|
import com.github.damontecres.wholphin.ui.data.RowColumn
|
||||||
import com.github.damontecres.wholphin.ui.detail.discover.getDiscoverRating
|
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.listToDotString
|
import com.github.damontecres.wholphin.ui.listToDotString
|
||||||
import com.github.damontecres.wholphin.ui.main.HomePageHeader
|
import com.github.damontecres.wholphin.ui.main.HomePageHeader
|
||||||
|
|
@ -57,9 +57,9 @@ import com.github.damontecres.wholphin.ui.util.StringProvider
|
||||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||||
import com.github.damontecres.wholphin.util.DiscoverRequestType
|
import com.github.damontecres.wholphin.util.DiscoverRequestType
|
||||||
import com.github.damontecres.wholphin.util.successValue
|
import com.github.damontecres.wholphin.util.successValue
|
||||||
import com.google.common.cache.CacheBuilder
|
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import org.jellyfin.sdk.model.UUID
|
import org.jellyfin.sdk.model.UUID
|
||||||
|
|
@ -73,11 +73,12 @@ class SeerrDiscoverViewModel
|
||||||
constructor(
|
constructor(
|
||||||
@param:ApplicationContext private val context: Context,
|
@param:ApplicationContext private val context: Context,
|
||||||
private val seerrService: SeerrService,
|
private val seerrService: SeerrService,
|
||||||
|
private val ratingsService: SeerrRatingsService,
|
||||||
val navigationManager: NavigationManager,
|
val navigationManager: NavigationManager,
|
||||||
private val backdropService: BackdropService,
|
private val backdropService: BackdropService,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
val state = MutableStateFlow<DiscoverState>(DiscoverState())
|
val state = MutableStateFlow<DiscoverState>(DiscoverState())
|
||||||
val rating = MutableStateFlow<Map<Int, DiscoverRating>>(mapOf())
|
val rating = MutableStateFlow<Map<Pair<SeerrItemType, Int>, SourceRatings>>(mapOf())
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launchIO {
|
viewModelScope.launchIO {
|
||||||
|
|
@ -246,50 +247,23 @@ class SeerrDiscoverViewModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ratingCache =
|
private var ratingJob: Job? = null
|
||||||
CacheBuilder
|
|
||||||
.newBuilder()
|
|
||||||
.maximumSize(100)
|
|
||||||
.build<Int, DiscoverRating>()
|
|
||||||
|
|
||||||
// TODO this is not very efficient
|
/**
|
||||||
|
* Fetch the ratings for the focused item, cancelling any previous request that is still running
|
||||||
|
*/
|
||||||
fun fetchRating(
|
fun fetchRating(
|
||||||
id: Int,
|
id: Int,
|
||||||
type: SeerrItemType,
|
type: SeerrItemType,
|
||||||
) {
|
) {
|
||||||
viewModelScope.launchIO {
|
val key = type to id
|
||||||
val cachedResult = ratingCache.getIfPresent(id)
|
if (key in rating.value) return
|
||||||
if (cachedResult != null) {
|
ratingJob?.cancel()
|
||||||
return@launchIO
|
ratingJob =
|
||||||
|
viewModelScope.launchIO {
|
||||||
|
val result = ratingsService.get(type, id) ?: return@launchIO
|
||||||
|
rating.update { it + (key to result) }
|
||||||
}
|
}
|
||||||
val result =
|
|
||||||
getDiscoverRating(id) {
|
|
||||||
when (type) {
|
|
||||||
SeerrItemType.MOVIE -> {
|
|
||||||
DiscoverRating(
|
|
||||||
seerrService.api.moviesApi.movieMovieIdRatingsGet(movieId = id),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SeerrItemType.TV -> {
|
|
||||||
DiscoverRating(seerrService.api.tvApi.tvTvIdRatingsGet(tvId = id))
|
|
||||||
}
|
|
||||||
|
|
||||||
SeerrItemType.PERSON -> {
|
|
||||||
DiscoverRating(null, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
SeerrItemType.UNKNOWN -> {
|
|
||||||
DiscoverRating(null, null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: DiscoverRating(null, null)
|
|
||||||
|
|
||||||
ratingCache.put(id, result)
|
|
||||||
rating.update {
|
|
||||||
ratingCache.asMap().toMap()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -424,14 +398,8 @@ fun SeerrDiscoverPage(
|
||||||
?.toString()
|
?.toString()
|
||||||
?.let(::add)
|
?.let(::add)
|
||||||
}.let {
|
}.let {
|
||||||
val rating = focusedItem.id.let { ratingMap[it] }
|
val rating = ratingMap[focusedItem.item.type to focusedItem.id]
|
||||||
val str =
|
QuickDetailsData(listToDotString(it, rating))
|
||||||
listToDotString(
|
|
||||||
it,
|
|
||||||
rating?.audienceRating,
|
|
||||||
rating?.criticRating?.toFloat(),
|
|
||||||
)
|
|
||||||
QuickDetailsData(str)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue