diff --git a/app/src/main/java/com/github/damontecres/dolphin/data/model/Chapter.kt b/app/src/main/java/com/github/damontecres/dolphin/data/model/Chapter.kt new file mode 100644 index 00000000..71a5e856 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/data/model/Chapter.kt @@ -0,0 +1,36 @@ +package com.github.damontecres.dolphin.data.model + +import org.jellyfin.sdk.api.client.ApiClient +import org.jellyfin.sdk.api.client.extensions.imageApi +import org.jellyfin.sdk.model.api.BaseItemDto +import org.jellyfin.sdk.model.api.ImageType +import org.jellyfin.sdk.model.extensions.ticks +import kotlin.time.Duration + +data class Chapter( + val name: String?, + val position: Duration, + val imageUrl: String?, +) { + companion object { + fun fromDto( + dto: BaseItemDto, + api: ApiClient, + ): List = + dto.chapters + ?.mapIndexed { index, chapter -> + Chapter( + chapter.name, + chapter.startPositionTicks.ticks, + chapter.imageTag?.let { + api.imageApi.getItemImageUrl( + itemId = dto.id, + imageType = ImageType.CHAPTER, + tag = it, + imageIndex = index, + ) + }, + ) + }.orEmpty() + } +} diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterCard.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterCard.kt new file mode 100644 index 00000000..4729280c --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterCard.kt @@ -0,0 +1,65 @@ +package com.github.damontecres.dolphin.ui.cards + +import androidx.compose.foundation.background +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import androidx.tv.material3.Card +import androidx.tv.material3.Text +import coil3.compose.AsyncImage +import com.github.damontecres.dolphin.ui.AppColors +import kotlin.time.Duration + +@Composable +fun ChapterCard( + name: String?, + position: Duration, + imageUrl: String?, + onClick: () -> Unit, + modifier: Modifier = Modifier, + cardHeight: Dp = 140.dp, + aspectRatio: Float = 16f / 9, + onLongClick: (() -> Unit)? = null, + interactionSource: MutableInteractionSource? = null, +) { + Card( + modifier = modifier.size(cardHeight * aspectRatio, cardHeight), + onClick = onClick, + onLongClick = onLongClick, + interactionSource = interactionSource, + ) { + Box(modifier = Modifier.fillMaxSize()) { + AsyncImage( + model = imageUrl, + contentDescription = null, + contentScale = ContentScale.Fit, + modifier = Modifier.fillMaxSize(), + ) + Column( + modifier = + Modifier + .align(Alignment.BottomStart) + .fillMaxWidth() + .background(AppColors.TransparentBlack50), + ) { + name?.let { + Text( + text = it, + ) + } + Text( + text = position.toString(), + ) + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterRow.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterRow.kt new file mode 100644 index 00000000..c540d6a5 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/ChapterRow.kt @@ -0,0 +1,57 @@ +package com.github.damontecres.dolphin.ui.cards + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.focusRestorer +import androidx.compose.ui.unit.dp +import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.Text +import com.github.damontecres.dolphin.data.model.Chapter + +@Composable +fun ChapterRow( + chapters: List, + onClick: (Chapter) -> Unit, + modifier: Modifier = Modifier, + onLongClick: ((Chapter) -> Unit)? = null, +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = modifier, + ) { + Text( + text = "Chapters", + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onBackground, + ) + LazyRow( + state = rememberLazyListState(), + horizontalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(8.dp), + modifier = + Modifier + .padding(start = 16.dp) + .fillMaxWidth() + .focusRestorer(), + ) { + itemsIndexed(chapters) { index, item -> + ChapterCard( + name = item.name, + position = item.position, + imageUrl = item.imageUrl, + onClick = { onClick(item) }, + modifier = Modifier, + onLongClick = onLongClick?.let { { it(item) } }, + ) + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/cards/PersonRow.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/PersonRow.kt new file mode 100644 index 00000000..0cd5b7d6 --- /dev/null +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/cards/PersonRow.kt @@ -0,0 +1,55 @@ +package com.github.damontecres.dolphin.ui.cards + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.focusRestorer +import androidx.compose.ui.unit.dp +import androidx.tv.material3.MaterialTheme +import androidx.tv.material3.Text +import com.github.damontecres.dolphin.data.model.Person + +@Composable +fun PersonRow( + people: List, + onClick: (Person) -> Unit, + modifier: Modifier = Modifier, + onLongClick: ((Person) -> Unit)? = null, +) { + Column( + verticalArrangement = Arrangement.spacedBy(8.dp), + modifier = modifier, + ) { + Text( + text = "People", + style = MaterialTheme.typography.titleLarge, + color = MaterialTheme.colorScheme.onBackground, + ) + LazyRow( + state = rememberLazyListState(), + horizontalArrangement = Arrangement.spacedBy(16.dp), + contentPadding = PaddingValues(8.dp), + modifier = + Modifier + .padding(start = 16.dp) + .fillMaxWidth() + .focusRestorer(), + ) { + itemsIndexed(people) { index, item -> + PersonCard( + item = item, + onClick = { onClick.invoke(item) }, + onLongClick = { onLongClick?.invoke(item) }, + modifier = Modifier, + ) + } + } + } +} diff --git a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetails.kt b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetails.kt index c1dcdb6d..efb32b1e 100644 --- a/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetails.kt +++ b/app/src/main/java/com/github/damontecres/dolphin/ui/detail/movie/MovieDetails.kt @@ -5,12 +5,10 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxHeight +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 @@ -25,7 +23,6 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.focus.focusRestorer import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale @@ -34,13 +31,14 @@ import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import androidx.tv.material3.MaterialTheme -import androidx.tv.material3.Text import coil3.compose.AsyncImage import com.github.damontecres.dolphin.data.model.BaseItem +import com.github.damontecres.dolphin.data.model.Chapter import com.github.damontecres.dolphin.data.model.Person import com.github.damontecres.dolphin.data.model.Video import com.github.damontecres.dolphin.preferences.UserPreferences -import com.github.damontecres.dolphin.ui.cards.PersonCard +import com.github.damontecres.dolphin.ui.cards.ChapterRow +import com.github.damontecres.dolphin.ui.cards.PersonRow import com.github.damontecres.dolphin.ui.components.ErrorMessage import com.github.damontecres.dolphin.ui.components.ExpandablePlayButtons import com.github.damontecres.dolphin.ui.components.LoadingPage @@ -68,6 +66,7 @@ class MovieViewModel api: ApiClient, ) : LoadingItemViewModel