mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-08 23:51:21 +02:00
Add more to discover tab
This commit is contained in:
parent
f43ee6b36c
commit
27dc031012
5 changed files with 140 additions and 8 deletions
|
|
@ -50,6 +50,27 @@ class SeerrService
|
|||
?.map(::DiscoverItem)
|
||||
.orEmpty()
|
||||
|
||||
suspend fun trending(page: Int = 1): List<DiscoverItem> =
|
||||
api.searchApi
|
||||
.discoverTrendingGet(page = page)
|
||||
.results
|
||||
?.map(::DiscoverItem)
|
||||
.orEmpty()
|
||||
|
||||
suspend fun upcomingMovies(page: Int = 1): List<DiscoverItem> =
|
||||
api.searchApi
|
||||
.discoverMoviesUpcomingGet(page = page)
|
||||
.results
|
||||
?.map(::DiscoverItem)
|
||||
.orEmpty()
|
||||
|
||||
suspend fun upcomingTv(page: Int = 1): List<DiscoverItem> =
|
||||
api.searchApi
|
||||
.discoverTvUpcomingGet(page = page)
|
||||
.results
|
||||
?.map(::DiscoverItem)
|
||||
.orEmpty()
|
||||
|
||||
/**
|
||||
* Get [DiscoverItem]s similar to the JF items such as movies, series, or people
|
||||
*
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
package com.github.damontecres.wholphin.ui.detail.discover
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
||||
import com.github.damontecres.wholphin.ui.components.DotSeparatedRow
|
||||
import timber.log.Timber
|
||||
|
||||
@Composable
|
||||
fun DiscoverQuickDetails(
|
||||
item: DiscoverItem?,
|
||||
rating: DiscoverRating?,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Timber.v("id=${item?.id}, rating=$rating")
|
||||
val context = LocalContext.current
|
||||
val details =
|
||||
remember(item) {
|
||||
buildList {
|
||||
item
|
||||
?.releaseDate
|
||||
?.year
|
||||
?.toString()
|
||||
?.let(::add)
|
||||
}
|
||||
}
|
||||
DotSeparatedRow(
|
||||
texts = details,
|
||||
communityRating = rating?.audienceRating,
|
||||
criticRating = rating?.criticRating?.toFloat(),
|
||||
textStyle = MaterialTheme.typography.titleSmall,
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
|
|
@ -32,6 +32,8 @@ import androidx.tv.material3.MaterialTheme
|
|||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
||||
import com.github.damontecres.wholphin.data.model.SeerrItemType
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
import com.github.damontecres.wholphin.services.BackdropService
|
||||
import com.github.damontecres.wholphin.services.NavigationManager
|
||||
|
|
@ -40,11 +42,13 @@ import com.github.damontecres.wholphin.ui.cards.DiscoverItemCard
|
|||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||
import com.github.damontecres.wholphin.ui.components.ErrorMessage
|
||||
import com.github.damontecres.wholphin.ui.data.RowColumn
|
||||
import com.github.damontecres.wholphin.ui.detail.discover.DiscoverQuickDetails
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.main.HomePageHeader
|
||||
import com.github.damontecres.wholphin.ui.rememberPosition
|
||||
import com.github.damontecres.wholphin.ui.tryRequestFocus
|
||||
import com.github.damontecres.wholphin.util.DataLoadingState
|
||||
import com.google.common.cache.CacheBuilder
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
|
@ -63,6 +67,7 @@ class SeerrDiscoverViewModel
|
|||
private val backdropService: BackdropService,
|
||||
) : ViewModel() {
|
||||
val state = MutableStateFlow<DiscoverState>(DiscoverState())
|
||||
val rating = MutableStateFlow<Map<Int, DiscoverRating>>(mapOf())
|
||||
|
||||
init {
|
||||
viewModelScope.launchIO {
|
||||
|
|
@ -74,6 +79,21 @@ class SeerrDiscoverViewModel
|
|||
fetchAndUpdateState(seerrService::discoverTv) {
|
||||
this.copy(tv = DiscoverRowData(context.getString(R.string.tv_shows), it))
|
||||
}
|
||||
fetchAndUpdateState(seerrService::trending) {
|
||||
this.copy(trending = DiscoverRowData(context.getString(R.string.trending), it))
|
||||
}
|
||||
fetchAndUpdateState(seerrService::upcomingMovies) {
|
||||
this.copy(
|
||||
upcomingMovies =
|
||||
DiscoverRowData(context.getString(R.string.upcoming_movies), it),
|
||||
)
|
||||
}
|
||||
fetchAndUpdateState(seerrService::upcomingTv) {
|
||||
this.copy(
|
||||
upcomingTv =
|
||||
DiscoverRowData(context.getString(R.string.upcoming_tv), it),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchAndUpdateState(
|
||||
|
|
@ -101,6 +121,49 @@ class SeerrDiscoverViewModel
|
|||
viewModelScope.launchIO {
|
||||
if (item != null) {
|
||||
backdropService.submit("discover_${item.id}", item.backDropUrl)
|
||||
fetchRating(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val ratingCache =
|
||||
CacheBuilder
|
||||
.newBuilder()
|
||||
.maximumSize(100)
|
||||
.build<Int, DiscoverRating>()
|
||||
|
||||
// TODO this is not very efficient
|
||||
fun fetchRating(item: DiscoverItem) {
|
||||
viewModelScope.launchIO {
|
||||
val cachedResult = ratingCache.getIfPresent(item.id)
|
||||
if (cachedResult != null) {
|
||||
return@launchIO
|
||||
}
|
||||
val result =
|
||||
when (item.type) {
|
||||
SeerrItemType.MOVIE -> {
|
||||
DiscoverRating(
|
||||
seerrService.api.moviesApi.movieMovieIdRatingsGet(
|
||||
movieId = item.id,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
SeerrItemType.TV -> {
|
||||
DiscoverRating(seerrService.api.tvApi.tvTvIdRatingsGet(tvId = item.id))
|
||||
}
|
||||
|
||||
SeerrItemType.PERSON -> {
|
||||
DiscoverRating(null, null)
|
||||
}
|
||||
|
||||
SeerrItemType.UNKNOWN -> {
|
||||
DiscoverRating(null, null)
|
||||
}
|
||||
}
|
||||
ratingCache.put(item.id, result)
|
||||
rating.update {
|
||||
ratingCache.asMap().toMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -118,6 +181,9 @@ data class DiscoverRowData(
|
|||
data class DiscoverState(
|
||||
val movies: DiscoverRowData = DiscoverRowData.EMPTY,
|
||||
val tv: DiscoverRowData = DiscoverRowData.EMPTY,
|
||||
val trending: DiscoverRowData = DiscoverRowData.EMPTY,
|
||||
val upcomingMovies: DiscoverRowData = DiscoverRowData.EMPTY,
|
||||
val upcomingTv: DiscoverRowData = DiscoverRowData.EMPTY,
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
@ -127,7 +193,9 @@ fun SeerrDiscoverPage(
|
|||
viewModel: SeerrDiscoverViewModel = hiltViewModel(),
|
||||
) {
|
||||
val state by viewModel.state.collectAsState()
|
||||
val rows = listOf(state.movies, state.tv)
|
||||
val rows =
|
||||
listOf(state.trending, state.movies, state.tv, state.upcomingMovies, state.upcomingTv)
|
||||
val ratingMap by viewModel.rating.collectAsState()
|
||||
|
||||
val focusRequesters = remember(2) { List(rows.size) { FocusRequester() } }
|
||||
var position by rememberPosition(0, -1)
|
||||
|
|
@ -141,8 +209,8 @@ fun SeerrDiscoverPage(
|
|||
viewModel.updateBackdrop(focusedItem)
|
||||
}
|
||||
var firstFocused by rememberSaveable { mutableStateOf(false) }
|
||||
LaunchedEffect(state.movies) {
|
||||
if (!firstFocused && state.movies.items is DataLoadingState.Success<*>) {
|
||||
LaunchedEffect(state.trending) {
|
||||
if (!firstFocused && state.trending.items is DataLoadingState.Success<*>) {
|
||||
firstFocused = focusRequesters.getOrNull(0)?.tryRequestFocus("discover") == true
|
||||
}
|
||||
}
|
||||
|
|
@ -156,12 +224,15 @@ fun SeerrDiscoverPage(
|
|||
overview = focusedItem?.overview,
|
||||
overviewTwoLines = true,
|
||||
quickDetails = {
|
||||
// TODO
|
||||
DiscoverQuickDetails(
|
||||
item = focusedItem,
|
||||
rating = focusedItem?.id?.let { ratingMap[it] },
|
||||
)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxHeight(.33f)
|
||||
.padding(top = 48.dp, bottom = 32.dp, start = 32.dp),
|
||||
.padding(top = 24.dp, bottom = 16.dp, start = 32.dp)
|
||||
.fillMaxHeight(.25f),
|
||||
)
|
||||
LazyColumn(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
|
|
|
|||
|
|
@ -640,8 +640,7 @@ fun NavigationDrawerScope.NavItem(
|
|||
}
|
||||
|
||||
NavDrawerItem.Discover -> {
|
||||
// TODO seerr
|
||||
R.string.fa_list_ul
|
||||
R.string.fa_magnifying_glass_plus
|
||||
}
|
||||
|
||||
is ServerNavDrawerItem -> {
|
||||
|
|
|
|||
|
|
@ -428,6 +428,9 @@
|
|||
<string name="password">Password</string>
|
||||
<string name="username">Username</string>
|
||||
<string name="url">URL</string>
|
||||
<string name="trending">Trending</string>
|
||||
<string name="upcoming_movies">Upcoming Movies</string>
|
||||
<string name="upcoming_tv">Upcoming TV Shows</string>
|
||||
|
||||
<string-array name="theme_song_volume">
|
||||
<item>Disabled</item>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue