mirror of
https://github.com/JustinZeus/Wholphin.git
synced 2026-07-09 08:01:20 +02:00
Show button for trailers instead of card row (#618)
## Description On both movie & series detail pages, show a button to play trailers instead of the row of cards below. The button works like this: - If no trailers, the button shows "No trailers" and is disabled/non-clickable - If only a single trailer, the button shows "Play trailer" and clicking it plays the trailer - Otherwise, shows "Trailers" and clicking displays a dialog to choose one Local trailers are shown first in the list. Then there is an attempt to sort the trailers for the dialog so that names with "Official Trailer" or "Official Theatrical Trailer" are listed first and "Teaser" is listed last. This isn't perfect and doesn't work for non-English, but there's no other metadata to use. ### Related issues Closes #408
This commit is contained in:
parent
b8e8a1d913
commit
0fe8e5d988
12 changed files with 218 additions and 170 deletions
|
|
@ -14,4 +14,5 @@ data class LocalTrailer(
|
|||
data class RemoteTrailer(
|
||||
override val name: String,
|
||||
val url: String,
|
||||
val subtitle: String?,
|
||||
) : Trailer
|
||||
|
|
|
|||
|
|
@ -22,31 +22,53 @@ class TrailerService
|
|||
@param:ApplicationContext private val context: Context,
|
||||
private val api: ApiClient,
|
||||
) {
|
||||
suspend fun getTrailers(item: BaseItem): List<Trailer> {
|
||||
val remoteTrailers =
|
||||
item.data.remoteTrailers
|
||||
?.mapNotNull { t ->
|
||||
t.url?.let { url ->
|
||||
val name =
|
||||
t.name
|
||||
// TODO would be nice to clean up the trailer name
|
||||
fun getRemoteTrailers(item: BaseItem): List<Trailer> =
|
||||
item.data.remoteTrailers
|
||||
?.mapNotNull { t ->
|
||||
t.url?.let { url ->
|
||||
val name =
|
||||
t.name
|
||||
// TODO would be nice to clean up the trailer name
|
||||
// ?.replace(item.name ?: "", "")
|
||||
// ?.removePrefix(" - ")
|
||||
?: context.getString(R.string.trailer)
|
||||
RemoteTrailer(name, url)
|
||||
}
|
||||
}.orEmpty()
|
||||
.sortedBy { it.name }
|
||||
val localTrailerCount = item.data.localTrailerCount ?: 0
|
||||
?: context.getString(R.string.trailer)
|
||||
val subtitle =
|
||||
when (url.toUri().host) {
|
||||
"youtube.com", "www.youtube.com" -> "YouTube"
|
||||
else -> null
|
||||
}
|
||||
RemoteTrailer(name, url, subtitle)
|
||||
}
|
||||
}.orEmpty()
|
||||
.sortedWith(
|
||||
compareBy(
|
||||
{
|
||||
// Try to show official trailers first & teasers last
|
||||
when {
|
||||
it.name.contains("Official Trailer", true) -> 0
|
||||
it.name.contains("Official Theatrical Trailer", true) -> 0
|
||||
it.name.contains("Teaser", true) -> 10
|
||||
it.name.contains("Trailer", true) -> 1
|
||||
else -> 5
|
||||
}
|
||||
},
|
||||
{
|
||||
it.name
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
suspend fun getLocalTrailers(item: BaseItem): List<Trailer> {
|
||||
val localTrailerCount = item.data.localTrailerCount ?: return emptyList()
|
||||
val localTrailers =
|
||||
if (localTrailerCount > 0) {
|
||||
api.userLibraryApi.getLocalTrailers(item.id).content.map {
|
||||
LocalTrailer(BaseItem.Companion.from(it, api))
|
||||
LocalTrailer(BaseItem.from(it, api))
|
||||
}
|
||||
} else {
|
||||
listOf()
|
||||
}
|
||||
return localTrailers + remoteTrailers
|
||||
return localTrailers
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.gestures.scrollBy
|
|||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.BoxScope
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
|
|
@ -239,47 +240,48 @@ fun DialogPopupContent(
|
|||
) {
|
||||
val elevatedContainerColor =
|
||||
MaterialTheme.colorScheme.surfaceColorAtElevation(elevation)
|
||||
LazyColumn(
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier =
|
||||
modifier
|
||||
// .widthIn(min = 520.dp, max = 300.dp)
|
||||
// .dialogFocusable()
|
||||
.graphicsLayer {
|
||||
this.clip = true
|
||||
this.shape = RoundedCornerShape(28.0.dp)
|
||||
}.drawBehind { drawRect(color = elevatedContainerColor) }
|
||||
.padding(PaddingValues(24.dp)),
|
||||
) {
|
||||
stickyHeader {
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
}
|
||||
items(dialogItems) {
|
||||
when (it) {
|
||||
is DialogItemDivider -> {
|
||||
HorizontalDivider(Modifier.height(16.dp))
|
||||
}
|
||||
Text(
|
||||
text = title,
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
)
|
||||
LazyColumn(
|
||||
modifier = Modifier,
|
||||
) {
|
||||
items(dialogItems) {
|
||||
when (it) {
|
||||
is DialogItemDivider -> {
|
||||
HorizontalDivider(Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
is DialogItem -> {
|
||||
ListItem(
|
||||
selected = false,
|
||||
enabled = !waiting && it.enabled,
|
||||
onClick = {
|
||||
if (dismissOnClick) {
|
||||
onDismissRequest.invoke()
|
||||
}
|
||||
it.onClick.invoke()
|
||||
},
|
||||
headlineContent = it.headlineContent,
|
||||
overlineContent = it.overlineContent,
|
||||
supportingContent = it.supportingContent,
|
||||
leadingContent = it.leadingContent,
|
||||
trailingContent = it.trailingContent,
|
||||
modifier = Modifier,
|
||||
)
|
||||
is DialogItem -> {
|
||||
ListItem(
|
||||
selected = false,
|
||||
enabled = !waiting && it.enabled,
|
||||
onClick = {
|
||||
if (dismissOnClick) {
|
||||
onDismissRequest.invoke()
|
||||
}
|
||||
it.onClick.invoke()
|
||||
},
|
||||
headlineContent = it.headlineContent,
|
||||
overlineContent = it.overlineContent,
|
||||
supportingContent = it.supportingContent,
|
||||
leadingContent = it.leadingContent,
|
||||
trailingContent = it.trailingContent,
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,10 @@ import androidx.compose.material.icons.filled.MoreVert
|
|||
import androidx.compose.material.icons.filled.PlayArrow
|
||||
import androidx.compose.material.icons.filled.Refresh
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
|
|
@ -40,6 +43,7 @@ import androidx.tv.material3.Icon
|
|||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.Trailer
|
||||
import com.github.damontecres.wholphin.ui.FontAwesome
|
||||
import com.github.damontecres.wholphin.ui.PreviewTvSpec
|
||||
import com.github.damontecres.wholphin.ui.data.SortAndDirection
|
||||
|
|
@ -59,10 +63,12 @@ fun ExpandablePlayButtons(
|
|||
resumePosition: Duration,
|
||||
watched: Boolean,
|
||||
favorite: Boolean,
|
||||
trailers: List<Trailer>?,
|
||||
playOnClick: (position: Duration) -> Unit,
|
||||
watchOnClick: () -> Unit,
|
||||
favoriteOnClick: () -> Unit,
|
||||
moreOnClick: () -> Unit,
|
||||
trailerOnClick: (Trailer) -> Unit,
|
||||
buttonOnFocusChanged: (FocusState) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
|
|
@ -134,6 +140,16 @@ fun ExpandablePlayButtons(
|
|||
)
|
||||
}
|
||||
|
||||
if (trailers != null) {
|
||||
item("trailers") {
|
||||
TrailerButton(
|
||||
trailers = trailers,
|
||||
trailerOnClick = trailerOnClick,
|
||||
modifier = Modifier.onFocusChanged(buttonOnFocusChanged),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// More button
|
||||
item("more") {
|
||||
ExpandablePlayButton(
|
||||
|
|
@ -213,6 +229,7 @@ fun ExpandableFaButton(
|
|||
modifier: Modifier = Modifier,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
iconColor: Color = Color.Unspecified,
|
||||
enabled: Boolean = true,
|
||||
) {
|
||||
val isFocused = interactionSource.collectIsFocusedAsState().value
|
||||
Button(
|
||||
|
|
@ -225,6 +242,7 @@ fun ExpandableFaButton(
|
|||
),
|
||||
contentPadding = DefaultButtonPadding,
|
||||
interactionSource = interactionSource,
|
||||
enabled = enabled,
|
||||
) {
|
||||
Box(
|
||||
modifier =
|
||||
|
|
@ -251,6 +269,42 @@ fun ExpandableFaButton(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TrailerButton(
|
||||
trailers: List<Trailer>,
|
||||
trailerOnClick: (Trailer) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
var showDialog by remember { mutableStateOf(false) }
|
||||
ExpandableFaButton(
|
||||
title =
|
||||
if (trailers.isEmpty()) {
|
||||
R.string.no_trailers
|
||||
} else if (trailers.size == 1) {
|
||||
R.string.play_trailer
|
||||
} else {
|
||||
R.string.trailers
|
||||
},
|
||||
iconStringRes = R.string.fa_film,
|
||||
enabled = trailers.isNotEmpty(),
|
||||
onClick = {
|
||||
if (trailers.size == 1) {
|
||||
trailerOnClick.invoke(trailers.first())
|
||||
} else {
|
||||
showDialog = true
|
||||
}
|
||||
},
|
||||
modifier = modifier,
|
||||
)
|
||||
if (showDialog) {
|
||||
TrailerDialog(
|
||||
onDismissRequest = { showDialog = false },
|
||||
trailers = trailers,
|
||||
onClick = trailerOnClick,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@PreviewTvSpec
|
||||
@Composable
|
||||
private fun ExpandablePlayButtonsPreview() {
|
||||
|
|
@ -264,6 +318,8 @@ private fun ExpandablePlayButtonsPreview() {
|
|||
favoriteOnClick = {},
|
||||
moreOnClick = {},
|
||||
buttonOnFocusChanged = {},
|
||||
trailers = listOf(),
|
||||
trailerOnClick = {},
|
||||
modifier = Modifier,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
package com.github.damontecres.wholphin.ui.components
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
||||
import com.github.damontecres.wholphin.data.model.RemoteTrailer
|
||||
import com.github.damontecres.wholphin.data.model.Trailer
|
||||
|
||||
@Composable
|
||||
fun TrailerDialog(
|
||||
onDismissRequest: () -> Unit,
|
||||
trailers: List<Trailer>,
|
||||
onClick: (Trailer) -> Unit,
|
||||
) {
|
||||
val trailersStr = stringResource(R.string.play_trailer)
|
||||
val localStr = stringResource(R.string.local)
|
||||
val externalStr = stringResource(R.string.external_track)
|
||||
val params =
|
||||
remember(trailers) {
|
||||
DialogParams(
|
||||
fromLongClick = false,
|
||||
title = trailersStr,
|
||||
items =
|
||||
trailers.map { trailer ->
|
||||
DialogItem(
|
||||
headlineContent = {
|
||||
Text(trailer.name)
|
||||
},
|
||||
supportingContent = {
|
||||
val subtitle =
|
||||
when (trailer) {
|
||||
is LocalTrailer -> localStr
|
||||
is RemoteTrailer -> trailer.subtitle ?: externalStr
|
||||
}
|
||||
Text(
|
||||
text = subtitle,
|
||||
)
|
||||
},
|
||||
onClick = { onClick.invoke(trailer) },
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
DialogPopup(
|
||||
params = params,
|
||||
onDismissRequest = onDismissRequest,
|
||||
)
|
||||
}
|
||||
|
|
@ -334,6 +334,8 @@ fun EpisodeDetailsContent(
|
|||
}
|
||||
}
|
||||
},
|
||||
trailers = null,
|
||||
trailerOnClick = {},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
|
|||
|
|
@ -8,9 +8,6 @@ import androidx.compose.foundation.layout.fillMaxSize
|
|||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyRow
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.foundation.relocation.BringIntoViewRequester
|
||||
import androidx.compose.foundation.relocation.bringIntoViewRequester
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -23,24 +20,18 @@ import androidx.compose.runtime.setValue
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.focus.focusRestorer
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.core.net.toUri
|
||||
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
|
||||
import androidx.lifecycle.compose.LifecycleResumeEffect
|
||||
import androidx.tv.material3.MaterialTheme
|
||||
import androidx.tv.material3.Text
|
||||
import com.github.damontecres.wholphin.R
|
||||
import com.github.damontecres.wholphin.data.ChosenStreams
|
||||
import com.github.damontecres.wholphin.data.ExtrasItem
|
||||
import com.github.damontecres.wholphin.data.model.BaseItem
|
||||
import com.github.damontecres.wholphin.data.model.Chapter
|
||||
import com.github.damontecres.wholphin.data.model.LocalTrailer
|
||||
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.aspectRatioFloat
|
||||
import com.github.damontecres.wholphin.preferences.UserPreferences
|
||||
|
|
@ -436,6 +427,11 @@ fun MovieDetailsContent(
|
|||
}
|
||||
}
|
||||
},
|
||||
trailers = trailers,
|
||||
trailerOnClick = {
|
||||
position = TRAILER_ROW
|
||||
trailerOnClick.invoke(it)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
|
|
@ -463,21 +459,6 @@ fun MovieDetailsContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
if (trailers.isNotEmpty()) {
|
||||
item {
|
||||
TrailerRow(
|
||||
trailers = trailers,
|
||||
onClickTrailer = {
|
||||
position = TRAILER_ROW
|
||||
trailerOnClick.invoke(it)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.focusRequester(focusRequesters[TRAILER_ROW]),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (chapters.isNotEmpty()) {
|
||||
item {
|
||||
ChapterRow(
|
||||
|
|
@ -545,78 +526,3 @@ fun MovieDetailsContent(
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TrailerRow(
|
||||
trailers: List<Trailer>,
|
||||
onClickTrailer: (Trailer) -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val state = rememberLazyListState()
|
||||
val firstFocus = remember { FocusRequester() }
|
||||
Column(
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp),
|
||||
modifier = modifier,
|
||||
) {
|
||||
Text(
|
||||
text = stringResource(R.string.trailers),
|
||||
style = MaterialTheme.typography.titleLarge,
|
||||
color = MaterialTheme.colorScheme.onBackground,
|
||||
)
|
||||
LazyRow(
|
||||
state = state,
|
||||
horizontalArrangement = Arrangement.spacedBy(16.dp),
|
||||
contentPadding = PaddingValues(horizontal = 24.dp, vertical = 8.dp),
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.focusRestorer(firstFocus),
|
||||
) {
|
||||
itemsIndexed(trailers) { index, item ->
|
||||
val cardModifier =
|
||||
if (index == 0) {
|
||||
Modifier.focusRequester(firstFocus)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
when (item) {
|
||||
is LocalTrailer -> {
|
||||
SeasonCard(
|
||||
item = item.baseItem,
|
||||
onClick = { onClickTrailer.invoke(item) },
|
||||
onLongClick = {},
|
||||
imageHeight = Cards.height2x3,
|
||||
imageWidth = Dp.Unspecified,
|
||||
showImageOverlay = false,
|
||||
modifier = cardModifier,
|
||||
)
|
||||
}
|
||||
|
||||
is RemoteTrailer -> {
|
||||
val subtitle =
|
||||
when (item.url.toUri().host) {
|
||||
"youtube.com", "www.youtube.com" -> "YouTube"
|
||||
else -> null
|
||||
}
|
||||
SeasonCard(
|
||||
title = item.name,
|
||||
subtitle = subtitle,
|
||||
name = item.name,
|
||||
imageUrl = null,
|
||||
isFavorite = false,
|
||||
isPlayed = false,
|
||||
unplayedItemCount = 0,
|
||||
playedPercentage = 0.0,
|
||||
onClick = { onClickTrailer.invoke(item) },
|
||||
onLongClick = {},
|
||||
modifier = cardModifier,
|
||||
showImageOverlay = false,
|
||||
imageHeight = Cards.height2x3,
|
||||
imageWidth = Dp.Unspecified,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import com.github.damontecres.wholphin.services.TrailerService
|
|||
import com.github.damontecres.wholphin.services.UserPreferencesService
|
||||
import com.github.damontecres.wholphin.ui.SlimItemFields
|
||||
import com.github.damontecres.wholphin.ui.launchIO
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.setValueOnMain
|
||||
import com.github.damontecres.wholphin.util.ExceptionHandler
|
||||
|
|
@ -116,16 +117,19 @@ class MovieViewModel
|
|||
item,
|
||||
userPreferencesService.getCurrent(),
|
||||
)
|
||||
val remoteTrailers = trailerService.getRemoteTrailers(item)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@MovieViewModel.item.value = item
|
||||
chosenStreams.value = result
|
||||
this@MovieViewModel.trailers.value = remoteTrailers
|
||||
loading.value = LoadingState.Success
|
||||
backdropService.submit(item)
|
||||
}
|
||||
viewModelScope.launchIO {
|
||||
val trailers = trailerService.getTrailers(item)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@MovieViewModel.trailers.value = trailers
|
||||
trailerService.getLocalTrailers(item).letNotEmpty { localTrailers ->
|
||||
withContext(Dispatchers.Main) {
|
||||
this@MovieViewModel.trailers.value = localTrailers + remoteTrailers
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModelScope.launchIO {
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ fun FocusedEpisodeFooter(
|
|||
watchOnClick = watchOnClick,
|
||||
favoriteOnClick = favoriteOnClick,
|
||||
buttonOnFocusChanged = buttonOnFocusChanged,
|
||||
trailers = null,
|
||||
trailerOnClick = {},
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,7 @@ import com.github.damontecres.wholphin.ui.components.LoadingPage
|
|||
import com.github.damontecres.wholphin.ui.components.Optional
|
||||
import com.github.damontecres.wholphin.ui.components.OverviewText
|
||||
import com.github.damontecres.wholphin.ui.components.SeriesQuickDetails
|
||||
import com.github.damontecres.wholphin.ui.components.TrailerButton
|
||||
import com.github.damontecres.wholphin.ui.data.AddPlaylistViewModel
|
||||
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialog
|
||||
import com.github.damontecres.wholphin.ui.data.ItemDetailsDialogInfo
|
||||
|
|
@ -70,7 +71,6 @@ import com.github.damontecres.wholphin.ui.detail.PlaylistDialog
|
|||
import com.github.damontecres.wholphin.ui.detail.PlaylistLoadingState
|
||||
import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItemsForHome
|
||||
import com.github.damontecres.wholphin.ui.detail.buildMoreDialogItemsForPerson
|
||||
import com.github.damontecres.wholphin.ui.detail.movie.TrailerRow
|
||||
import com.github.damontecres.wholphin.ui.letNotEmpty
|
||||
import com.github.damontecres.wholphin.ui.nav.Destination
|
||||
import com.github.damontecres.wholphin.ui.rememberInt
|
||||
|
|
@ -411,6 +411,18 @@ fun SeriesDetailsContent(
|
|||
}
|
||||
},
|
||||
)
|
||||
TrailerButton(
|
||||
trailers = trailers,
|
||||
trailerOnClick = trailerOnClick,
|
||||
modifier =
|
||||
Modifier.onFocusChanged {
|
||||
if (it.isFocused) {
|
||||
scope.launch(ExceptionHandler()) {
|
||||
bringIntoViewRequester.bringIntoView()
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
item {
|
||||
|
|
@ -472,21 +484,6 @@ fun SeriesDetailsContent(
|
|||
)
|
||||
}
|
||||
}
|
||||
if (trailers.isNotEmpty()) {
|
||||
item {
|
||||
TrailerRow(
|
||||
trailers = trailers,
|
||||
onClickTrailer = {
|
||||
position = TRAILER_ROW
|
||||
trailerOnClick.invoke(it)
|
||||
},
|
||||
modifier =
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.focusRequester(focusRequesters[TRAILER_ROW]),
|
||||
)
|
||||
}
|
||||
}
|
||||
if (extras.isNotEmpty()) {
|
||||
item {
|
||||
ExtrasRow(
|
||||
|
|
|
|||
|
|
@ -165,8 +165,9 @@ class SeriesViewModel
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
val remoteTrailers = trailerService.getRemoteTrailers(item)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@SeriesViewModel.trailers.value = remoteTrailers
|
||||
this@SeriesViewModel.position.update {
|
||||
it.copy(
|
||||
episodeRowIndex =
|
||||
|
|
@ -179,9 +180,10 @@ class SeriesViewModel
|
|||
}
|
||||
if (seriesPageType == SeriesPageType.DETAILS) {
|
||||
viewModelScope.launchIO {
|
||||
val trailers = trailerService.getTrailers(item)
|
||||
withContext(Dispatchers.Main) {
|
||||
this@SeriesViewModel.trailers.value = trailers
|
||||
trailerService.getLocalTrailers(item).letNotEmpty { localTrailers ->
|
||||
withContext(Dispatchers.Main) {
|
||||
this@SeriesViewModel.trailers.value = localTrailers + remoteTrailers
|
||||
}
|
||||
}
|
||||
}
|
||||
viewModelScope.launchIO {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue