mirror of
https://github.com/bbara04/Purefin.git
synced 2026-04-01 01:30:08 +02:00
Move TV detail overview and playback into body
This commit is contained in:
@@ -40,6 +40,8 @@ class EpisodeScreenContentTest {
|
|||||||
composeRule.onNodeWithText("Severance").assertIsDisplayed()
|
composeRule.onNodeWithText("Severance").assertIsDisplayed()
|
||||||
composeRule.onNodeWithText("The You You Are").assertIsDisplayed()
|
composeRule.onNodeWithText("The You You Are").assertIsDisplayed()
|
||||||
composeRule.onNodeWithText("Episode 4").assertIsDisplayed()
|
composeRule.onNodeWithText("Episode 4").assertIsDisplayed()
|
||||||
|
composeRule.onNodeWithText("Overview").assertIsDisplayed()
|
||||||
|
composeRule.onAllNodesWithText("Playback").assertCountEquals(1)
|
||||||
composeRule.onNodeWithTag(EpisodePlayButtonTag).assertIsDisplayed().assertIsFocused()
|
composeRule.onNodeWithTag(EpisodePlayButtonTag).assertIsDisplayed().assertIsFocused()
|
||||||
composeRule.onNodeWithText("Series").assertIsDisplayed()
|
composeRule.onNodeWithText("Series").assertIsDisplayed()
|
||||||
}
|
}
|
||||||
@@ -63,6 +65,8 @@ class EpisodeScreenContentTest {
|
|||||||
|
|
||||||
composeRule.waitForIdle()
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
composeRule.onNodeWithText("Overview").assertIsDisplayed()
|
||||||
|
composeRule.onAllNodesWithText("Playback").assertCountEquals(1)
|
||||||
composeRule.onNodeWithTag(EpisodePlayButtonTag).assertIsDisplayed()
|
composeRule.onNodeWithTag(EpisodePlayButtonTag).assertIsDisplayed()
|
||||||
composeRule.onAllNodesWithText("Series").assertCountEquals(0)
|
composeRule.onAllNodesWithText("Series").assertCountEquals(0)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package hu.bbara.purefin.app.content.movie
|
package hu.bbara.purefin.app.content.movie
|
||||||
|
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
|
import androidx.compose.ui.test.assertCountEquals
|
||||||
import androidx.compose.ui.test.assertIsDisplayed
|
import androidx.compose.ui.test.assertIsDisplayed
|
||||||
import androidx.compose.ui.test.assertIsFocused
|
import androidx.compose.ui.test.assertIsFocused
|
||||||
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
import androidx.compose.ui.test.junit4.createAndroidComposeRule
|
||||||
|
import androidx.compose.ui.test.onAllNodesWithText
|
||||||
import androidx.compose.ui.test.onNodeWithContentDescription
|
import androidx.compose.ui.test.onNodeWithContentDescription
|
||||||
import androidx.compose.ui.test.onNodeWithTag
|
import androidx.compose.ui.test.onNodeWithTag
|
||||||
import androidx.compose.ui.test.onNodeWithText
|
import androidx.compose.ui.test.onNodeWithText
|
||||||
@@ -34,7 +36,8 @@ class MovieScreenContentTest {
|
|||||||
composeRule.waitForIdle()
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
composeRule.onNodeWithText("Blade Runner 2049").assertIsDisplayed()
|
composeRule.onNodeWithText("Blade Runner 2049").assertIsDisplayed()
|
||||||
composeRule.onNodeWithText("Playback").assertIsDisplayed()
|
composeRule.onNodeWithText("Overview").assertIsDisplayed()
|
||||||
|
composeRule.onAllNodesWithText("Playback").assertCountEquals(1)
|
||||||
composeRule.onNodeWithTag(MoviePlayButtonTag).assertIsDisplayed().assertIsFocused()
|
composeRule.onNodeWithTag(MoviePlayButtonTag).assertIsDisplayed().assertIsFocused()
|
||||||
composeRule.onNodeWithContentDescription("Back").assertIsDisplayed()
|
composeRule.onNodeWithContentDescription("Back").assertIsDisplayed()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ class SeriesScreenContentTest {
|
|||||||
composeRule.waitForIdle()
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
composeRule.onNodeWithText("Severance").assertIsDisplayed()
|
composeRule.onNodeWithText("Severance").assertIsDisplayed()
|
||||||
|
composeRule.onNodeWithText("Overview").assertIsDisplayed()
|
||||||
composeRule.onNodeWithText("Up Next").assertIsDisplayed()
|
composeRule.onNodeWithText("Up Next").assertIsDisplayed()
|
||||||
composeRule.onNodeWithTag(SeriesPlayButtonTag).assertIsDisplayed().assertIsFocused()
|
composeRule.onNodeWithTag(SeriesPlayButtonTag).assertIsDisplayed().assertIsFocused()
|
||||||
composeRule.onNodeWithText("Season 1").assertIsDisplayed()
|
composeRule.onNodeWithText("Season 1").assertIsDisplayed()
|
||||||
@@ -55,6 +56,7 @@ class SeriesScreenContentTest {
|
|||||||
|
|
||||||
composeRule.waitForIdle()
|
composeRule.waitForIdle()
|
||||||
|
|
||||||
|
composeRule.onNodeWithText("Overview").assertIsDisplayed()
|
||||||
composeRule.onNodeWithText("Library Status").assertIsDisplayed()
|
composeRule.onNodeWithText("Library Status").assertIsDisplayed()
|
||||||
composeRule.onNodeWithTag(SeriesFirstSeasonTabTag).assertIsDisplayed().assertIsFocused()
|
composeRule.onNodeWithTag(SeriesFirstSeasonTabTag).assertIsDisplayed().assertIsFocused()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import hu.bbara.purefin.common.ui.MediaMetaChip
|
import hu.bbara.purefin.common.ui.MediaMetaChip
|
||||||
import hu.bbara.purefin.common.ui.MediaSynopsis
|
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBarShortcut
|
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBarShortcut
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
|
||||||
import hu.bbara.purefin.common.ui.components.MediaResumeButton
|
import hu.bbara.purefin.common.ui.components.MediaResumeButton
|
||||||
import hu.bbara.purefin.core.data.navigation.Route
|
import hu.bbara.purefin.core.data.navigation.Route
|
||||||
import hu.bbara.purefin.core.model.Episode
|
import hu.bbara.purefin.core.model.Episode
|
||||||
@@ -137,44 +135,6 @@ internal fun EpisodeHeroSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun EpisodeOverviewPanel(
|
|
||||||
episode: Episode,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
val scheme = MaterialTheme.colorScheme
|
|
||||||
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.85f)
|
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
|
||||||
MediaSynopsis(
|
|
||||||
synopsis = episode.synopsis,
|
|
||||||
title = "Overview",
|
|
||||||
titleColor = scheme.onSurface,
|
|
||||||
bodyColor = mutedStrong,
|
|
||||||
titleFontSize = 20.sp,
|
|
||||||
bodyFontSize = 16.sp,
|
|
||||||
bodyLineHeight = 24.sp,
|
|
||||||
titleSpacing = 10.dp,
|
|
||||||
collapsedLines = 5,
|
|
||||||
collapseInitially = false
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
Text(
|
|
||||||
text = "Playback",
|
|
||||||
color = scheme.onSurface,
|
|
||||||
fontSize = 20.sp,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
|
||||||
MediaPlaybackSettings(
|
|
||||||
backgroundColor = scheme.surfaceContainerHigh,
|
|
||||||
foregroundColor = scheme.onSurface,
|
|
||||||
audioTrack = "ENG",
|
|
||||||
subtitles = "ENG"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Episode.playButtonText(): String {
|
private fun Episode.playButtonText(): String {
|
||||||
return if ((progress ?: 0.0) > 0.0 && !watched) "Resume" else "Play"
|
return if ((progress ?: 0.0) > 0.0 && !watched) "Resume" else "Play"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package hu.bbara.purefin.app.content.episode
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -14,7 +15,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import hu.bbara.purefin.common.ui.MediaCastRow
|
import hu.bbara.purefin.common.ui.MediaCastRow
|
||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailHeaderRow
|
import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection
|
||||||
|
import hu.bbara.purefin.common.ui.components.MediaDetailPlaybackSection
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
||||||
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
||||||
import hu.bbara.purefin.core.data.navigation.EpisodeDto
|
import hu.bbara.purefin.core.data.navigation.EpisodeDto
|
||||||
@@ -99,30 +101,39 @@ internal fun EpisodeScreenContent(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
heroContent = {
|
heroContent = {
|
||||||
MediaDetailHeaderRow(
|
|
||||||
leftContent = { headerModifier ->
|
|
||||||
EpisodeHeroSection(
|
EpisodeHeroSection(
|
||||||
episode = episode,
|
episode = episode,
|
||||||
seriesTitle = seriesTitle,
|
seriesTitle = seriesTitle,
|
||||||
onPlay = onPlay,
|
onPlay = onPlay,
|
||||||
playFocusRequester = playFocusRequester,
|
playFocusRequester = playFocusRequester,
|
||||||
modifier = headerModifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
|
||||||
},
|
|
||||||
rightContent = { panelModifier ->
|
|
||||||
EpisodeOverviewPanel(
|
|
||||||
episode = episode,
|
|
||||||
modifier = panelModifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
item {
|
||||||
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
MediaDetailOverviewSection(
|
||||||
|
synopsis = episode.synopsis,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
|
MediaDetailPlaybackSection(
|
||||||
|
audioTrack = "ENG",
|
||||||
|
subtitles = "ENG",
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
if (episode.cast.isNotEmpty()) {
|
if (episode.cast.isNotEmpty()) {
|
||||||
item {
|
item {
|
||||||
Column(modifier = it) {
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
MediaDetailSectionTitle(text = "Cast")
|
MediaDetailSectionTitle(text = "Cast")
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
MediaCastRow(cast = episode.cast)
|
MediaCastRow(cast = episode.cast)
|
||||||
|
|||||||
@@ -21,9 +21,7 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import hu.bbara.purefin.common.ui.MediaMetaChip
|
import hu.bbara.purefin.common.ui.MediaMetaChip
|
||||||
import hu.bbara.purefin.common.ui.MediaSynopsis
|
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
||||||
import hu.bbara.purefin.common.ui.components.MediaPlaybackSettings
|
|
||||||
import hu.bbara.purefin.common.ui.components.MediaResumeButton
|
import hu.bbara.purefin.common.ui.components.MediaResumeButton
|
||||||
import hu.bbara.purefin.core.model.Movie
|
import hu.bbara.purefin.core.model.Movie
|
||||||
|
|
||||||
@@ -94,44 +92,6 @@ internal fun MovieHeroSection(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
|
||||||
internal fun MovieOverviewPanel(
|
|
||||||
movie: Movie,
|
|
||||||
modifier: Modifier = Modifier
|
|
||||||
) {
|
|
||||||
val scheme = MaterialTheme.colorScheme
|
|
||||||
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.85f)
|
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
|
||||||
MediaSynopsis(
|
|
||||||
synopsis = movie.synopsis,
|
|
||||||
title = "Overview",
|
|
||||||
titleColor = scheme.onSurface,
|
|
||||||
bodyColor = mutedStrong,
|
|
||||||
titleFontSize = 20.sp,
|
|
||||||
bodyFontSize = 16.sp,
|
|
||||||
bodyLineHeight = 24.sp,
|
|
||||||
titleSpacing = 10.dp,
|
|
||||||
collapsedLines = 5,
|
|
||||||
collapseInitially = false
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
Text(
|
|
||||||
text = "Playback",
|
|
||||||
color = scheme.onSurface,
|
|
||||||
fontSize = 20.sp,
|
|
||||||
fontWeight = FontWeight.Bold
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
|
||||||
MediaPlaybackSettings(
|
|
||||||
backgroundColor = scheme.surfaceContainerHigh,
|
|
||||||
foregroundColor = scheme.onSurface,
|
|
||||||
audioTrack = movie.audioTrack,
|
|
||||||
subtitles = movie.subtitles
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Movie.playButtonText(): String {
|
private fun Movie.playButtonText(): String {
|
||||||
return if ((progress ?: 0.0) > 0.0 && !watched) "Resume" else "Play"
|
return if ((progress ?: 0.0) > 0.0 && !watched) "Resume" else "Play"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package hu.bbara.purefin.app.content.movie
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -14,7 +15,8 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import hu.bbara.purefin.common.ui.MediaCastRow
|
import hu.bbara.purefin.common.ui.MediaCastRow
|
||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailHeaderRow
|
import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection
|
||||||
|
import hu.bbara.purefin.common.ui.components.MediaDetailPlaybackSection
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
||||||
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
||||||
import hu.bbara.purefin.core.data.navigation.MovieDto
|
import hu.bbara.purefin.core.data.navigation.MovieDto
|
||||||
@@ -67,29 +69,38 @@ internal fun MovieScreenContent(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
heroContent = {
|
heroContent = {
|
||||||
MediaDetailHeaderRow(
|
|
||||||
leftContent = { headerModifier ->
|
|
||||||
MovieHeroSection(
|
MovieHeroSection(
|
||||||
movie = movie,
|
movie = movie,
|
||||||
onPlay = onPlay,
|
onPlay = onPlay,
|
||||||
playFocusRequester = playFocusRequester,
|
playFocusRequester = playFocusRequester,
|
||||||
modifier = headerModifier
|
modifier = Modifier.fillMaxWidth()
|
||||||
)
|
|
||||||
},
|
|
||||||
rightContent = { panelModifier ->
|
|
||||||
MovieOverviewPanel(
|
|
||||||
movie = movie,
|
|
||||||
modifier = panelModifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
Spacer(modifier = Modifier.height(12.dp))
|
Spacer(modifier = Modifier.height(12.dp))
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
item {
|
||||||
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
MediaDetailOverviewSection(
|
||||||
|
synopsis = movie.synopsis,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
|
MediaDetailPlaybackSection(
|
||||||
|
audioTrack = movie.audioTrack,
|
||||||
|
subtitles = movie.subtitles,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(20.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
if (movie.cast.isNotEmpty()) {
|
if (movie.cast.isNotEmpty()) {
|
||||||
item {
|
item {
|
||||||
Column(modifier = it) {
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
Spacer(modifier = Modifier.height(8.dp))
|
|
||||||
MediaDetailSectionTitle(text = "Cast")
|
MediaDetailSectionTitle(text = "Cast")
|
||||||
Spacer(modifier = Modifier.height(14.dp))
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
MediaCastRow(cast = movie.cast)
|
MediaCastRow(cast = movie.cast)
|
||||||
|
|||||||
@@ -55,7 +55,6 @@ import androidx.compose.ui.unit.sp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import hu.bbara.purefin.common.ui.MediaCastRow
|
import hu.bbara.purefin.common.ui.MediaCastRow
|
||||||
import hu.bbara.purefin.common.ui.MediaMetaChip
|
import hu.bbara.purefin.common.ui.MediaMetaChip
|
||||||
import hu.bbara.purefin.common.ui.MediaSynopsis
|
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
import hu.bbara.purefin.common.ui.components.MediaDetailsTopBar
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
||||||
import hu.bbara.purefin.common.ui.components.MediaProgressBar
|
import hu.bbara.purefin.common.ui.components.MediaProgressBar
|
||||||
@@ -249,28 +248,16 @@ internal fun SeriesHeroSection(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
internal fun SeriesOverviewPanel(
|
internal fun SeriesStatusPanel(
|
||||||
series: Series,
|
|
||||||
nextUpEpisode: Episode?,
|
nextUpEpisode: Episode?,
|
||||||
|
seasonCount: Int,
|
||||||
|
unwatchedEpisodeCount: Int,
|
||||||
modifier: Modifier = Modifier
|
modifier: Modifier = Modifier
|
||||||
) {
|
) {
|
||||||
val scheme = MaterialTheme.colorScheme
|
val scheme = MaterialTheme.colorScheme
|
||||||
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.85f)
|
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.85f)
|
||||||
|
|
||||||
Column(modifier = modifier) {
|
Column(modifier = modifier) {
|
||||||
MediaSynopsis(
|
|
||||||
synopsis = series.synopsis,
|
|
||||||
title = "Overview",
|
|
||||||
titleColor = scheme.onSurface,
|
|
||||||
bodyColor = mutedStrong,
|
|
||||||
titleFontSize = 20.sp,
|
|
||||||
bodyFontSize = 16.sp,
|
|
||||||
bodyLineHeight = 24.sp,
|
|
||||||
titleSpacing = 10.dp,
|
|
||||||
collapsedLines = 5,
|
|
||||||
collapseInitially = false
|
|
||||||
)
|
|
||||||
Spacer(modifier = Modifier.height(24.dp))
|
|
||||||
MediaDetailSectionTitle(
|
MediaDetailSectionTitle(
|
||||||
text = if (nextUpEpisode != null) "Up Next" else "Library Status",
|
text = if (nextUpEpisode != null) "Up Next" else "Library Status",
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
@@ -280,7 +267,7 @@ internal fun SeriesOverviewPanel(
|
|||||||
text = if (nextUpEpisode != null) {
|
text = if (nextUpEpisode != null) {
|
||||||
nextUpEpisode.title
|
nextUpEpisode.title
|
||||||
} else {
|
} else {
|
||||||
"${series.seasonCount} seasons ready to browse"
|
"$seasonCount seasons ready to browse"
|
||||||
},
|
},
|
||||||
color = scheme.onSurface,
|
color = scheme.onSurface,
|
||||||
fontSize = 18.sp,
|
fontSize = 18.sp,
|
||||||
@@ -293,7 +280,7 @@ internal fun SeriesOverviewPanel(
|
|||||||
text = if (nextUpEpisode != null) {
|
text = if (nextUpEpisode != null) {
|
||||||
"Episode ${nextUpEpisode.index} • ${nextUpEpisode.runtime}"
|
"Episode ${nextUpEpisode.index} • ${nextUpEpisode.runtime}"
|
||||||
} else {
|
} else {
|
||||||
"${series.unwatchedEpisodeCount} unwatched episodes"
|
"$unwatchedEpisodeCount unwatched episodes"
|
||||||
},
|
},
|
||||||
color = mutedStrong,
|
color = mutedStrong,
|
||||||
fontSize = 14.sp,
|
fontSize = 14.sp,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package hu.bbara.purefin.app.content.series
|
|||||||
|
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.height
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
@@ -15,6 +16,7 @@ import androidx.compose.ui.unit.dp
|
|||||||
import androidx.hilt.navigation.compose.hiltViewModel
|
import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
import hu.bbara.purefin.common.ui.PurefinWaitingScreen
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailHeaderRow
|
import hu.bbara.purefin.common.ui.components.MediaDetailHeaderRow
|
||||||
|
import hu.bbara.purefin.common.ui.components.MediaDetailOverviewSection
|
||||||
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
import hu.bbara.purefin.common.ui.components.MediaDetailSectionTitle
|
||||||
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
import hu.bbara.purefin.common.ui.components.TvMediaDetailScaffold
|
||||||
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
import hu.bbara.purefin.core.data.navigation.SeriesDto
|
||||||
@@ -103,9 +105,10 @@ internal fun SeriesScreenContent(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
rightContent = { panelModifier ->
|
rightContent = { panelModifier ->
|
||||||
SeriesOverviewPanel(
|
SeriesStatusPanel(
|
||||||
series = series,
|
|
||||||
nextUpEpisode = nextUpEpisode,
|
nextUpEpisode = nextUpEpisode,
|
||||||
|
seasonCount = series.seasonCount,
|
||||||
|
unwatchedEpisodeCount = series.unwatchedEpisodeCount,
|
||||||
modifier = panelModifier
|
modifier = panelModifier
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -114,7 +117,16 @@ internal fun SeriesScreenContent(
|
|||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
|
Column(modifier = it.fillMaxWidth()) {
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
|
MediaDetailOverviewSection(
|
||||||
|
synopsis = series.synopsis,
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.height(24.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
item {
|
||||||
SeasonTabs(
|
SeasonTabs(
|
||||||
seasons = series.seasons,
|
seasons = series.seasons,
|
||||||
selectedSeason = selectedSeason.value,
|
selectedSeason = selectedSeason.value,
|
||||||
|
|||||||
@@ -7,8 +7,10 @@ import androidx.compose.foundation.layout.BoxScope
|
|||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.ColumnScope
|
import androidx.compose.foundation.layout.ColumnScope
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.LazyListScope
|
import androidx.compose.foundation.lazy.LazyListScope
|
||||||
@@ -22,6 +24,7 @@ import androidx.compose.ui.graphics.Brush
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import hu.bbara.purefin.common.ui.MediaSynopsis
|
||||||
|
|
||||||
internal val MediaDetailHorizontalPadding = 48.dp
|
internal val MediaDetailHorizontalPadding = 48.dp
|
||||||
private val MediaDetailPanelShape = RoundedCornerShape(28.dp)
|
private val MediaDetailPanelShape = RoundedCornerShape(28.dp)
|
||||||
@@ -114,6 +117,48 @@ internal fun MediaDetailSectionTitle(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun MediaDetailOverviewSection(
|
||||||
|
synopsis: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
|
MediaSynopsis(
|
||||||
|
synopsis = synopsis,
|
||||||
|
modifier = modifier,
|
||||||
|
title = "Overview",
|
||||||
|
titleColor = scheme.onBackground,
|
||||||
|
bodyColor = scheme.onSurfaceVariant.copy(alpha = 0.85f),
|
||||||
|
titleFontSize = 22.sp,
|
||||||
|
bodyFontSize = 16.sp,
|
||||||
|
bodyLineHeight = 24.sp,
|
||||||
|
titleSpacing = 14.dp,
|
||||||
|
collapsedLines = 5,
|
||||||
|
collapseInitially = false
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
internal fun MediaDetailPlaybackSection(
|
||||||
|
audioTrack: String,
|
||||||
|
subtitles: String,
|
||||||
|
modifier: Modifier = Modifier
|
||||||
|
) {
|
||||||
|
val scheme = MaterialTheme.colorScheme
|
||||||
|
|
||||||
|
Column(modifier = modifier) {
|
||||||
|
MediaDetailSectionTitle(text = "Playback")
|
||||||
|
Spacer(modifier = Modifier.height(14.dp))
|
||||||
|
MediaPlaybackSettings(
|
||||||
|
backgroundColor = scheme.surfaceContainerHigh,
|
||||||
|
foregroundColor = scheme.onBackground,
|
||||||
|
audioTrack = audioTrack,
|
||||||
|
subtitles = subtitles
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun MediaDetailHeroGradientOverlay() {
|
private fun MediaDetailHeroGradientOverlay() {
|
||||||
val background = MaterialTheme.colorScheme.background
|
val background = MaterialTheme.colorScheme.background
|
||||||
|
|||||||
Reference in New Issue
Block a user