mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 08:01:20 +02:00
Movie details improvements
This commit is contained in:
parent
69fb26a070
commit
5738d4732d
3 changed files with 86 additions and 77 deletions
|
|
@ -36,8 +36,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.ExtrasItem
|
import com.github.damontecres.wholphin.data.model.DiscoverItem
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
|
||||||
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
import com.github.damontecres.wholphin.data.model.DiscoverRating
|
||||||
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.Person
|
import com.github.damontecres.wholphin.data.model.Person
|
||||||
|
|
@ -46,7 +45,7 @@ import com.github.damontecres.wholphin.data.model.Trailer
|
||||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||||
import com.github.damontecres.wholphin.services.TrailerService
|
import com.github.damontecres.wholphin.services.TrailerService
|
||||||
import com.github.damontecres.wholphin.ui.Cards
|
import com.github.damontecres.wholphin.ui.Cards
|
||||||
import com.github.damontecres.wholphin.ui.cards.ExtrasRow
|
import com.github.damontecres.wholphin.ui.cards.DiscoverItemCard
|
||||||
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
import com.github.damontecres.wholphin.ui.cards.ItemRow
|
||||||
import com.github.damontecres.wholphin.ui.cards.PersonRow
|
import com.github.damontecres.wholphin.ui.cards.PersonRow
|
||||||
import com.github.damontecres.wholphin.ui.cards.SeasonCard
|
import com.github.damontecres.wholphin.ui.cards.SeasonCard
|
||||||
|
|
@ -59,7 +58,6 @@ import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
|
||||||
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialog
|
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialog
|
||||||
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialogInfo
|
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialogInfo
|
||||||
import com.github.damontecres.wholphin.ui.detail.MoreDialogActions
|
import com.github.damontecres.wholphin.ui.detail.MoreDialogActions
|
||||||
import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItemsForHome
|
|
||||||
import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItemsForPerson
|
import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItemsForPerson
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.rememberInt
|
import com.github.damontecres.wholphin.ui.rememberInt
|
||||||
|
|
@ -88,8 +86,8 @@ fun DiscoverMovieDetails(
|
||||||
val rating by viewModel.rating.observeAsState(null)
|
val rating by viewModel.rating.observeAsState(null)
|
||||||
val people by viewModel.people.observeAsState(listOf())
|
val people by viewModel.people.observeAsState(listOf())
|
||||||
val trailers by viewModel.trailers.observeAsState(listOf())
|
val trailers by viewModel.trailers.observeAsState(listOf())
|
||||||
val extras by viewModel.extras.observeAsState(listOf())
|
|
||||||
val similar by viewModel.similar.observeAsState(listOf())
|
val similar by viewModel.similar.observeAsState(listOf())
|
||||||
|
val recommended by viewModel.similar.observeAsState(listOf())
|
||||||
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
val loading by viewModel.loading.observeAsState(LoadingState.Loading)
|
||||||
|
|
||||||
var overviewDialog by remember { mutableStateOf<ItemDetailsDialogInfo?>(null) }
|
var overviewDialog by remember { mutableStateOf<ItemDetailsDialogInfo?>(null) }
|
||||||
|
|
@ -121,14 +119,14 @@ fun DiscoverMovieDetails(
|
||||||
movie = movie,
|
movie = movie,
|
||||||
rating = rating,
|
rating = rating,
|
||||||
people = people,
|
people = people,
|
||||||
extras = extras,
|
|
||||||
trailers = trailers,
|
trailers = trailers,
|
||||||
similar = similar,
|
similar = similar,
|
||||||
|
recommended = recommended,
|
||||||
requestOnClick = {
|
requestOnClick = {
|
||||||
// TODO seerr
|
// TODO seerr
|
||||||
},
|
},
|
||||||
onClickItem = { index, item ->
|
onClickItem = { index, item ->
|
||||||
viewModel.navigateTo(item.destination())
|
viewModel.navigateTo(Destination.DiscoveredItem(item))
|
||||||
},
|
},
|
||||||
onClickPerson = {
|
onClickPerson = {
|
||||||
},
|
},
|
||||||
|
|
@ -164,29 +162,10 @@ fun DiscoverMovieDetails(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
onLongClickSimilar = { index, similar ->
|
onLongClickSimilar = { index, similar ->
|
||||||
val items =
|
|
||||||
buildMoreDialogItemsForHome(
|
|
||||||
context = context,
|
|
||||||
item = similar,
|
|
||||||
seriesId = null,
|
|
||||||
playbackPosition = similar.playbackPosition,
|
|
||||||
watched = similar.played,
|
|
||||||
favorite = similar.favorite,
|
|
||||||
actions = moreActions,
|
|
||||||
)
|
|
||||||
moreDialog =
|
|
||||||
DialogParams(
|
|
||||||
fromLongClick = true,
|
|
||||||
title = similar.title ?: "",
|
|
||||||
items = items,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
trailerOnClick = {
|
trailerOnClick = {
|
||||||
TrailerService.onClick(context, it, viewModel::navigateTo)
|
TrailerService.onClick(context, it, viewModel::navigateTo)
|
||||||
},
|
},
|
||||||
onClickExtra = { index, extra ->
|
|
||||||
viewModel.navigateTo(extra.destination)
|
|
||||||
},
|
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -217,6 +196,7 @@ private const val TRAILER_ROW = PEOPLE_ROW + 1
|
||||||
private const val CHAPTER_ROW = TRAILER_ROW + 1
|
private const val CHAPTER_ROW = TRAILER_ROW + 1
|
||||||
private const val EXTRAS_ROW = CHAPTER_ROW + 1
|
private const val EXTRAS_ROW = CHAPTER_ROW + 1
|
||||||
private const val SIMILAR_ROW = EXTRAS_ROW + 1
|
private const val SIMILAR_ROW = EXTRAS_ROW + 1
|
||||||
|
private const val RECOMMENDED_ROW = SIMILAR_ROW + 1
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DiscoverMovieDetailsContent(
|
fun DiscoverMovieDetailsContent(
|
||||||
|
|
@ -225,23 +205,22 @@ fun DiscoverMovieDetailsContent(
|
||||||
rating: DiscoverRating?,
|
rating: DiscoverRating?,
|
||||||
people: List<Person>,
|
people: List<Person>,
|
||||||
trailers: List<Trailer>,
|
trailers: List<Trailer>,
|
||||||
extras: List<ExtrasItem>,
|
similar: List<DiscoverItem>,
|
||||||
similar: List<BaseItem>,
|
recommended: List<DiscoverItem>,
|
||||||
requestOnClick: () -> Unit,
|
requestOnClick: () -> Unit,
|
||||||
trailerOnClick: (Trailer) -> Unit,
|
trailerOnClick: (Trailer) -> Unit,
|
||||||
overviewOnClick: () -> Unit,
|
overviewOnClick: () -> Unit,
|
||||||
moreOnClick: () -> Unit,
|
moreOnClick: () -> Unit,
|
||||||
onClickItem: (Int, BaseItem) -> Unit,
|
onClickItem: (Int, DiscoverItem) -> Unit,
|
||||||
onClickPerson: (Person) -> Unit,
|
onClickPerson: (Person) -> Unit,
|
||||||
onLongClickPerson: (Int, Person) -> Unit,
|
onLongClickPerson: (Int, Person) -> Unit,
|
||||||
onLongClickSimilar: (Int, BaseItem) -> Unit,
|
onLongClickSimilar: (Int, DiscoverItem) -> Unit,
|
||||||
onClickExtra: (Int, ExtrasItem) -> Unit,
|
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
val context = LocalContext.current
|
val context = LocalContext.current
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
var position by rememberInt(0)
|
var position by rememberInt(0)
|
||||||
val focusRequesters = remember { List(SIMILAR_ROW + 1) { FocusRequester() } }
|
val focusRequesters = remember { List(RECOMMENDED_ROW + 1) { FocusRequester() } }
|
||||||
|
|
||||||
val bringIntoViewRequester = remember { BringIntoViewRequester() }
|
val bringIntoViewRequester = remember { BringIntoViewRequester() }
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
|
|
@ -329,22 +308,6 @@ fun DiscoverMovieDetailsContent(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extras.isNotEmpty()) {
|
|
||||||
item {
|
|
||||||
ExtrasRow(
|
|
||||||
extras = extras,
|
|
||||||
onClickItem = { index, item ->
|
|
||||||
position = EXTRAS_ROW
|
|
||||||
onClickExtra.invoke(index, item)
|
|
||||||
},
|
|
||||||
onLongClickItem = { _, _ -> },
|
|
||||||
modifier =
|
|
||||||
Modifier
|
|
||||||
.fillMaxWidth()
|
|
||||||
.focusRequester(focusRequesters[EXTRAS_ROW]),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (similar.isNotEmpty()) {
|
if (similar.isNotEmpty()) {
|
||||||
item {
|
item {
|
||||||
ItemRow(
|
ItemRow(
|
||||||
|
|
@ -359,14 +322,11 @@ fun DiscoverMovieDetailsContent(
|
||||||
onLongClickSimilar.invoke(index, similar)
|
onLongClickSimilar.invoke(index, similar)
|
||||||
},
|
},
|
||||||
cardContent = { index, item, mod, onClick, onLongClick ->
|
cardContent = { index, item, mod, onClick, onLongClick ->
|
||||||
SeasonCard(
|
DiscoverItemCard(
|
||||||
item = item,
|
item = item,
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
onLongClick = onLongClick,
|
onLongClick = onLongClick,
|
||||||
modifier = mod,
|
modifier = mod,
|
||||||
showImageOverlay = true,
|
|
||||||
imageHeight = Cards.height2x3,
|
|
||||||
imageWidth = Dp.Unspecified,
|
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
modifier =
|
modifier =
|
||||||
|
|
@ -376,6 +336,34 @@ fun DiscoverMovieDetailsContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (recommended.isNotEmpty()) {
|
||||||
|
item {
|
||||||
|
ItemRow(
|
||||||
|
title = stringResource(R.string.recommended),
|
||||||
|
items = similar,
|
||||||
|
onClickItem = { index, item ->
|
||||||
|
position = RECOMMENDED_ROW
|
||||||
|
onClickItem.invoke(index, item)
|
||||||
|
},
|
||||||
|
onLongClickItem = { index, similar ->
|
||||||
|
position = RECOMMENDED_ROW
|
||||||
|
onLongClickSimilar.invoke(index, similar)
|
||||||
|
},
|
||||||
|
cardContent = { index, item, mod, onClick, onLongClick ->
|
||||||
|
DiscoverItemCard(
|
||||||
|
item = item,
|
||||||
|
onClick = onClick,
|
||||||
|
onLongClick = onLongClick,
|
||||||
|
modifier = mod,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier =
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.focusRequester(focusRequesters[RECOMMENDED_ROW]),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||||
import com.github.damontecres.wholphin.ui.roundMinutes
|
import com.github.damontecres.wholphin.ui.roundMinutes
|
||||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.Locale
|
||||||
import kotlin.time.Duration.Companion.minutes
|
import kotlin.time.Duration.Companion.minutes
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -71,9 +72,18 @@ fun DiscoverMovieDetailsHeader(
|
||||||
?.roundMinutes
|
?.roundMinutes
|
||||||
?.toString()
|
?.toString()
|
||||||
?.let(::add)
|
?.let(::add)
|
||||||
movie.releases
|
val release =
|
||||||
?.results
|
movie.releases
|
||||||
?.firstOrNull()
|
?.results
|
||||||
|
?.firstOrNull { it.iso31661 == Locale.getDefault().country }
|
||||||
|
?: movie.releases
|
||||||
|
?.results
|
||||||
|
?.firstOrNull { it.iso31661 == Locale.US.country }
|
||||||
|
?: movie.releases
|
||||||
|
?.results
|
||||||
|
?.firstOrNull()
|
||||||
|
|
||||||
|
release
|
||||||
?.releaseDates
|
?.releaseDates
|
||||||
?.firstOrNull()
|
?.firstOrNull()
|
||||||
?.certification
|
?.certification
|
||||||
|
|
|
||||||
|
|
@ -5,17 +5,16 @@ import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
import com.github.damontecres.wholphin.api.seerr.model.MovieDetails
|
||||||
import com.github.damontecres.wholphin.data.ChosenStreams
|
import com.github.damontecres.wholphin.api.seerr.model.RelatedVideo
|
||||||
import com.github.damontecres.wholphin.data.ExtrasItem
|
|
||||||
import com.github.damontecres.wholphin.data.ServerRepository
|
import com.github.damontecres.wholphin.data.ServerRepository
|
||||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
|
||||||
import com.github.damontecres.wholphin.data.model.Chapter
|
|
||||||
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.DiscoverRating
|
||||||
import com.github.damontecres.wholphin.data.model.Person
|
import com.github.damontecres.wholphin.data.model.Person
|
||||||
|
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
||||||
import com.github.damontecres.wholphin.data.model.Trailer
|
import com.github.damontecres.wholphin.data.model.Trailer
|
||||||
import com.github.damontecres.wholphin.services.NavigationManager
|
import com.github.damontecres.wholphin.services.NavigationManager
|
||||||
import com.github.damontecres.wholphin.services.SeerrService
|
import com.github.damontecres.wholphin.services.SeerrService
|
||||||
|
import com.github.damontecres.wholphin.ui.isNotNullOrBlank
|
||||||
import com.github.damontecres.wholphin.ui.launchIO
|
import com.github.damontecres.wholphin.ui.launchIO
|
||||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||||
|
|
@ -58,10 +57,8 @@ class DiscoverMovieViewModel
|
||||||
|
|
||||||
val trailers = MutableLiveData<List<Trailer>>(listOf())
|
val trailers = MutableLiveData<List<Trailer>>(listOf())
|
||||||
val people = MutableLiveData<List<Person>>(listOf())
|
val people = MutableLiveData<List<Person>>(listOf())
|
||||||
val chapters = MutableLiveData<List<Chapter>>(listOf())
|
val similar = MutableLiveData<List<DiscoverItem>>(listOf())
|
||||||
val extras = MutableLiveData<List<ExtrasItem>>(listOf())
|
val recommended = MutableLiveData<List<DiscoverItem>>(listOf())
|
||||||
val similar = MutableLiveData<List<BaseItem>>()
|
|
||||||
val chosenStreams = MutableLiveData<ChosenStreams?>(null)
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
init()
|
init()
|
||||||
|
|
@ -96,6 +93,26 @@ class DiscoverMovieViewModel
|
||||||
val result = seerrService.api.moviesApi.movieMovieIdRatingsGet(movieId = item.id)
|
val result = seerrService.api.moviesApi.movieMovieIdRatingsGet(movieId = item.id)
|
||||||
rating.setValueOnMain(DiscoverRating(result))
|
rating.setValueOnMain(DiscoverRating(result))
|
||||||
}
|
}
|
||||||
|
if (!similar.isInitialized) {
|
||||||
|
viewModelScope.launchIO {
|
||||||
|
val result =
|
||||||
|
seerrService.api.moviesApi
|
||||||
|
.movieMovieIdSimilarGet(movieId = item.id, page = 2)
|
||||||
|
.results
|
||||||
|
?.map(::DiscoverItem)
|
||||||
|
.orEmpty()
|
||||||
|
similar.setValueOnMain(result)
|
||||||
|
}
|
||||||
|
viewModelScope.launchIO {
|
||||||
|
val result =
|
||||||
|
seerrService.api.moviesApi
|
||||||
|
.movieMovieIdRecommendationsGet(movieId = item.id, page = 2)
|
||||||
|
.results
|
||||||
|
?.map(::DiscoverItem)
|
||||||
|
.orEmpty()
|
||||||
|
similar.setValueOnMain(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
val people =
|
val people =
|
||||||
movie.credits
|
movie.credits
|
||||||
?.cast
|
?.cast
|
||||||
|
|
@ -122,20 +139,14 @@ class DiscoverMovieViewModel
|
||||||
)
|
)
|
||||||
}.orEmpty()
|
}.orEmpty()
|
||||||
this@DiscoverMovieViewModel.people.setValueOnMain(people)
|
this@DiscoverMovieViewModel.people.setValueOnMain(people)
|
||||||
if (!similar.isInitialized) {
|
val trailers =
|
||||||
// val similar =
|
movie.relatedVideos
|
||||||
// api.libraryApi
|
?.filter { it.type == RelatedVideo.Type.TRAILER }
|
||||||
// .getSimilarItems(
|
?.filter { it.name.isNotNullOrBlank() && it.url.isNotNullOrBlank() }
|
||||||
// GetSimilarItemsRequest(
|
?.map {
|
||||||
// userId = serverRepository.currentUser.value?.id,
|
RemoteTrailer(it.name!!, it.url!!)
|
||||||
// itemId = itemId,
|
}.orEmpty()
|
||||||
// fields = SlimItemFields,
|
this@DiscoverMovieViewModel.trailers.setValueOnMain(trailers)
|
||||||
// limit = 25,
|
|
||||||
// ),
|
|
||||||
// ).content.items
|
|
||||||
// .map { BaseItem.Companion.from(it, api) }
|
|
||||||
// this@DiscoverMovieViewModel.similar.setValueOnMain(similar)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun navigateTo(destination: Destination) {
|
fun navigateTo(destination: Destination) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue