Compare commits

...

7 Commits

17 changed files with 133 additions and 145 deletions

View File

@@ -12,6 +12,14 @@ Follow these instructions before making changes:
--- ---
## Ui principles
* Ui design should align with the material ui 3 design system
* For new components check https://m3.material.io/components if there is an available solution for the problem.
* Using Box components are a red flag and should be only used when there is no other option.
* When styling components check the material ui 3 site first and use it for the decision https://m3.material.io/styles
---
## Repository Expectations ## Repository Expectations
* Always use the currently used syntax in the codebase. Include examples for any naming you introduce. * Always use the currently used syntax in the codebase. Include examples for any naming you introduce.

View File

@@ -42,6 +42,7 @@ import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView import androidx.compose.ui.viewinterop.AndroidView
@@ -85,9 +86,13 @@ fun TvPlayerScreen(
val controlsAutoHideBlocked = isPlaylistExpanded || trackPanelType != null val controlsAutoHideBlocked = isPlaylistExpanded || trackPanelType != null
val context = LocalContext.current val context = LocalContext.current
LaunchedEffect(Unit) { val focusManager = LocalFocusManager.current
viewModel.setControlsAutoHideDelay(TV_CONTROLS_AUTO_HIDE_MS) val rootFocusRequester = remember { FocusRequester() }
} val controlsFocusRequester = remember { FocusRequester() }
val qualityButtonFocusRequester = remember { FocusRequester() }
val audioButtonFocusRequester = remember { FocusRequester() }
val subtitlesButtonFocusRequester = remember { FocusRequester() }
val skipButtonFocusRequester = remember { FocusRequester() }
LaunchedEffect(uiState.isPlaying) { LaunchedEffect(uiState.isPlaying) {
val activity = context as? Activity val activity = context as? Activity
if (uiState.isPlaying) { if (uiState.isPlaying) {
@@ -115,12 +120,6 @@ fun TvPlayerScreen(
) )
} }
val hiddenControlFocusRequester = remember { FocusRequester() }
val controlsFocusRequester = remember { FocusRequester() }
val qualityButtonFocusRequester = remember { FocusRequester() }
val audioButtonFocusRequester = remember { FocusRequester() }
val subtitlesButtonFocusRequester = remember { FocusRequester() }
val skipButtonFocusRequester = remember { FocusRequester() }
val expandPlaylist: () -> Unit = { val expandPlaylist: () -> Unit = {
if (!isPlaylistExpanded) { if (!isPlaylistExpanded) {
isPlaylistExpanded = true isPlaylistExpanded = true
@@ -181,16 +180,20 @@ fun TvPlayerScreen(
} }
} }
LaunchedEffect(controlsVisible, controlsAutoHideBlocked) { LaunchedEffect(
controlsVisible,
controlsAutoHideBlocked,
uiState.activeSkippableSegmentEndMs
) {
if (controlsAutoHideBlocked) return@LaunchedEffect if (controlsAutoHideBlocked) return@LaunchedEffect
if (controlsVisible) { if (controlsVisible) {
controlsFocusRequester.requestFocus() controlsFocusRequester.requestFocus()
} else { } else {
uiState.activeSkippableSegmentEndMs?.let { if (uiState.activeSkippableSegmentEndMs != null) {
skipButtonFocusRequester.requestFocus() skipButtonFocusRequester.requestFocus()
return@LaunchedEffect return@LaunchedEffect
} }
hiddenControlFocusRequester.requestFocus() focusManager.clearFocus()
} }
} }
@@ -239,7 +242,7 @@ fun TvPlayerScreen(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
.background(Color.Black) .background(Color.Black)
.focusRequester(hiddenControlFocusRequester) .focusRequester(rootFocusRequester)
.onPreviewKeyEvent { event -> .onPreviewKeyEvent { event ->
handleTvPlayerRootKeyEvent( handleTvPlayerRootKeyEvent(
event = event, event = event,
@@ -254,6 +257,8 @@ fun TvPlayerScreen(
onResumePlaybackWithoutShowingControls = resumePlaybackWithoutShowingControls, onResumePlaybackWithoutShowingControls = resumePlaybackWithoutShowingControls,
onSeekRelative = seekByWithoutShowingControls, onSeekRelative = seekByWithoutShowingControls,
onShowControls = showTvControls, onShowControls = showTvControls,
onSkipSegment = skipSegmentAndShowControls,
hasSkippableSegment = uiState.activeSkippableSegmentEndMs != null,
onTogglePlayPause = togglePlayPauseAndShowControls onTogglePlayPause = togglePlayPauseAndShowControls
) )
} }
@@ -385,6 +390,8 @@ internal fun handleTvPlayerRootKeyEvent(
onResumePlaybackWithoutShowingControls: () -> Unit, onResumePlaybackWithoutShowingControls: () -> Unit,
onSeekRelative: (Long) -> Unit, onSeekRelative: (Long) -> Unit,
onShowControls: () -> Unit, onShowControls: () -> Unit,
onSkipSegment: () -> Unit = {},
hasSkippableSegment: Boolean = false,
onTogglePlayPause: () -> Unit onTogglePlayPause: () -> Unit
): Boolean { ): Boolean {
if (event.type != KeyEventType.KeyDown) return false if (event.type != KeyEventType.KeyDown) return false
@@ -428,7 +435,9 @@ internal fun handleTvPlayerRootKeyEvent(
} }
Key.DirectionCenter, Key.Enter -> { Key.DirectionCenter, Key.Enter -> {
if (isPlaying) { if (hasSkippableSegment) {
onSkipSegment()
} else if (isPlaying) {
onPausePlaybackWithoutShowingControls() onPausePlaybackWithoutShowingControls()
} else { } else {
onResumePlaybackWithoutShowingControls() onResumePlaybackWithoutShowingControls()

View File

@@ -94,7 +94,7 @@ internal fun TvSeriesScreenContent(
series = series, series = series,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Spacer(modifier = Modifier.height(18.dp)) Spacer(modifier = Modifier.height(16.dp))
TvSeasonTabs( TvSeasonTabs(
seasons = series.seasons, seasons = series.seasons,
selectedSeason = selectedSeason, selectedSeason = selectedSeason,
@@ -103,7 +103,7 @@ internal fun TvSeriesScreenContent(
onSelect = { selectedSeason = it }, onSelect = { selectedSeason = it },
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) )
Spacer(modifier = Modifier.height(4.dp)) Spacer(modifier = Modifier.height(16.dp))
TvEpisodeCarousel( TvEpisodeCarousel(
episodes = selectedSeason.episodes, episodes = selectedSeason.episodes,
onPlayEpisode = { onPlayEpisode(it.id) }, onPlayEpisode = { onPlayEpisode(it.id) },

View File

@@ -6,12 +6,10 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.LocalBringIntoViewSpec import androidx.compose.foundation.gestures.LocalBringIntoViewSpec
import androidx.compose.foundation.horizontalScroll
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -20,10 +18,10 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.wrapContentWidth
import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.PlayCircle import androidx.compose.material.icons.outlined.PlayCircle
@@ -44,7 +42,6 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
@@ -52,6 +49,9 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow 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 androidx.tv.material3.Tab
import androidx.tv.material3.TabDefaults
import androidx.tv.material3.TabRow
import hu.bbara.purefin.image.ArtworkKind import hu.bbara.purefin.image.ArtworkKind
import hu.bbara.purefin.image.ImageUrlBuilder import hu.bbara.purefin.image.ImageUrlBuilder
import hu.bbara.purefin.model.CastMember import hu.bbara.purefin.model.CastMember
@@ -64,6 +64,7 @@ import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
import hu.bbara.purefin.ui.common.media.MediaMetadataFlowRow import hu.bbara.purefin.ui.common.media.MediaMetadataFlowRow
import hu.bbara.purefin.ui.screen.home.components.TvHomeRowBringIntoViewSpec import hu.bbara.purefin.ui.screen.home.components.TvHomeRowBringIntoViewSpec
import java.util.UUID import java.util.UUID
import androidx.tv.material3.Text as TvText
internal const val SeriesFirstSeasonTabTag = "series-first-season-tab" internal const val SeriesFirstSeasonTabTag = "series-first-season-tab"
internal const val SeriesNextUpEpisodeCardTag = "series-next-up-episode-card" internal const val SeriesNextUpEpisodeCardTag = "series-next-up-episode-card"
@@ -84,17 +85,21 @@ internal fun TvSeasonTabs(
firstItemTestTag: String? = null, firstItemTestTag: String? = null,
onSelect: (Season) -> Unit onSelect: (Season) -> Unit
) { ) {
Row( val selectedSeasonIndex = seasons.indexOf(selectedSeason).coerceAtLeast(0)
TabRow(
selectedTabIndex = selectedSeasonIndex,
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
.horizontalScroll(rememberScrollState()), .wrapContentWidth(Alignment.Start),
horizontalArrangement = Arrangement.spacedBy(20.dp) contentColor = MaterialTheme.colorScheme.onSurface
) { ) {
seasons.forEachIndexed { index, season -> seasons.forEachIndexed { index, season ->
TvSeasonTab( Tab(
name = season.name, selected = index == selectedSeasonIndex,
isSelected = season == selectedSeason, onFocus = { onSelect(season) },
onSelect = { onSelect(season) }, onClick = { onSelect(season) },
colors = TabDefaults.underlinedIndicatorTabColors(),
modifier = Modifier modifier = Modifier
.then( .then(
if (index == 0 && firstItemFocusRequester != null) { if (index == 0 && firstItemFocusRequester != null) {
@@ -110,47 +115,24 @@ internal fun TvSeasonTabs(
Modifier Modifier
} }
) )
) ) {
TvText(
text = season.name,
fontSize = 13.sp,
fontWeight = if (index == selectedSeasonIndex) {
FontWeight.Bold
} else {
FontWeight.Medium
},
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp)
)
}
} }
} }
} }
@Composable
private fun TvSeasonTab(
name: String,
isSelected: Boolean,
onSelect: () -> Unit,
modifier: Modifier = Modifier
) {
val scheme = MaterialTheme.colorScheme
val mutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f)
var isFocused by remember { mutableStateOf(false) }
val color = if (isSelected || isFocused) scheme.primary else mutedStrong
val underlineColor = if (isSelected || isFocused) scheme.primary else Color.Transparent
val underlineHeight = if (isFocused) 3.dp else 2.dp
Column(
modifier = modifier
.padding(bottom = 8.dp)
.onFocusChanged { isFocused = it.isFocused }
.clickable { onSelect() }
) {
Text(
text = name,
color = color,
fontSize = 13.sp,
fontWeight = if (isSelected || isFocused) FontWeight.Bold else FontWeight.Medium
)
Spacer(modifier = Modifier.height(8.dp))
Box(
modifier = Modifier
.height(underlineHeight)
.width(52.dp)
.background(underlineColor)
)
}
}
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)
@Composable @Composable
internal fun TvEpisodeCarousel( internal fun TvEpisodeCarousel(

View File

@@ -142,15 +142,15 @@ internal fun EpisodeDetails(
) )
VerticalDivider( VerticalDivider(
color = MaterialTheme.colorScheme.secondary, color = MaterialTheme.colorScheme.secondary,
thickness = 4.dp, thickness = 2.dp,
modifier = Modifier modifier = Modifier
.height(48.dp) .height(48.dp)
.padding(horizontal = 16.dp, vertical = 8.dp) .padding(horizontal = 16.dp, vertical = 8.dp)
) )
Row() { Row() {
MediaActionButton( MediaActionButton(
backgroundColor = MaterialTheme.colorScheme.secondary, backgroundColor = MaterialTheme.colorScheme.surface,
iconColor = MaterialTheme.colorScheme.onSecondary, iconColor = MaterialTheme.colorScheme.onSurface,
icon = when (downloadState) { icon = when (downloadState) {
is DownloadState.NotDownloaded -> Icons.Outlined.Download is DownloadState.NotDownloaded -> Icons.Outlined.Download
is DownloadState.Downloading -> Icons.Outlined.Close is DownloadState.Downloading -> Icons.Outlined.Close

View File

@@ -10,11 +10,12 @@ import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Collections import androidx.compose.material.icons.outlined.Collections
import androidx.compose.material.icons.outlined.Refresh import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.FilledTonalButton import androidx.compose.material3.FilledTonalButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -31,9 +32,9 @@ fun HomeEmptyState(
) { ) {
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
Surface( Card(
shape = RoundedCornerShape(30.dp), shape = RoundedCornerShape(30.dp),
color = scheme.surfaceContainerLow, colors = CardDefaults.cardColors(containerColor = scheme.surfaceContainerLow),
modifier = modifier.padding(horizontal = 16.dp) modifier = modifier.padding(horizontal = 16.dp)
) { ) {
Column( Column(

View File

@@ -38,10 +38,11 @@ fun HomeTopBar(
IconButton( IconButton(
onClick = onSearchClick, onClick = onSearchClick,
colors = IconButtonColors( colors = IconButtonColors(
containerColor = scheme.secondary, containerColor = scheme.surface,
contentColor = scheme.onSecondary, contentColor = scheme.onSurface,
disabledContainerColor = scheme.secondary, disabledContainerColor = scheme.surface,
disabledContentColor = scheme.onSecondary), disabledContentColor = scheme.onSurface
),
modifier = Modifier.size(50.dp), modifier = Modifier.size(50.dp),
) { ) {
Icon( Icon(
@@ -54,10 +55,11 @@ fun HomeTopBar(
IconButton( IconButton(
onClick = { isProfileMenuExpanded = true }, onClick = { isProfileMenuExpanded = true },
colors = IconButtonColors( colors = IconButtonColors(
containerColor = scheme.secondary, containerColor = scheme.surface,
contentColor = scheme.onSecondary, contentColor = scheme.onSurface,
disabledContainerColor = scheme.secondary, disabledContainerColor = scheme.surface,
disabledContentColor = scheme.onSecondary), disabledContentColor = scheme.onSurface
),
modifier = Modifier modifier = Modifier
.size(50.dp) .size(50.dp)
.clip(CircleShape), .clip(CircleShape),

View File

@@ -1,7 +1,6 @@
package hu.bbara.purefin.ui.screen.home.components.continuewatching package hu.bbara.purefin.ui.screen.home.components.continuewatching
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -11,8 +10,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -35,16 +35,13 @@ internal fun ContinueWatchingCard(
) { ) {
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
Surface( Card(
onClick = { onMediaSelected(item) },
shape = RoundedCornerShape(26.dp), shape = RoundedCornerShape(26.dp),
color = scheme.surfaceContainer, colors = CardDefaults.cardColors(containerColor = scheme.surfaceContainer),
modifier = modifier.width(280.dp) modifier = modifier.width(280.dp)
) { ) {
Column( Column(modifier = Modifier.fillMaxWidth()) {
modifier = Modifier
.fillMaxWidth()
.clickable { onMediaSelected(item) }
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -93,7 +90,7 @@ internal fun ContinueWatchingCard(
Text( Text(
text = item.secondaryText, text = item.secondaryText,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = scheme.onSurface, color = scheme.onSurfaceVariant,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )

View File

@@ -1,7 +1,6 @@
package hu.bbara.purefin.ui.screen.home.components.featured package hu.bbara.purefin.ui.screen.home.components.featured
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -11,13 +10,13 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
@@ -37,13 +36,12 @@ internal fun SuggestionCard(
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
val description = item.description.trim() val description = item.description.trim()
Surface( ElevatedCard(
color = scheme.surfaceContainerLow, onClick = onClick,
colors = CardDefaults.elevatedCardColors(containerColor = scheme.surfaceContainerLow),
elevation = CardDefaults.elevatedCardElevation(defaultElevation = 1.dp),
shape = RoundedCornerShape(30.dp), shape = RoundedCornerShape(30.dp),
modifier = modifier modifier = modifier.fillMaxWidth()
.fillMaxWidth()
.clip(RoundedCornerShape(30.dp))
.clickable(onClick = onClick)
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier

View File

@@ -1,7 +1,6 @@
package hu.bbara.purefin.ui.screen.home.components.library package hu.bbara.purefin.ui.screen.home.components.library
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -12,8 +11,9 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
@@ -37,16 +37,13 @@ internal fun HomeBrowseCard(
) { ) {
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
Surface( Card(
onClick = { onMediaSelected(uiModel) },
shape = RoundedCornerShape(12.dp), shape = RoundedCornerShape(12.dp),
color = scheme.surfaceContainer, colors = CardDefaults.cardColors(containerColor = scheme.surfaceContainer),
modifier = modifier.width(188.dp) modifier = modifier.width(188.dp)
) { ) {
Column( Column(modifier = Modifier.fillMaxWidth()) {
modifier = Modifier
.fillMaxWidth()
.clickable { onMediaSelected(uiModel) }
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -75,7 +72,7 @@ internal fun HomeBrowseCard(
} }
} }
Spacer(modifier = Modifier.height(10.dp)) Spacer(modifier = Modifier.height(10.dp))
Column(modifier = modifier.padding(12.dp)) { Column(modifier = Modifier.padding(12.dp)) {
Text( Text(
text = uiModel.primaryText, text = uiModel.primaryText,
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
@@ -87,7 +84,7 @@ internal fun HomeBrowseCard(
Text( Text(
text = uiModel.secondaryText, text = uiModel.secondaryText,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = scheme.onSurface, color = scheme.onSurfaceVariant,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )

View File

@@ -1,7 +1,6 @@
package hu.bbara.purefin.ui.screen.home.components.nextup package hu.bbara.purefin.ui.screen.home.components.nextup
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@@ -11,8 +10,9 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
@@ -33,16 +33,13 @@ internal fun NextUpCard(
) { ) {
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
Surface( Card(
onClick = { onMediaSelected(uiModel) },
shape = RoundedCornerShape(24.dp), shape = RoundedCornerShape(24.dp),
color = scheme.surfaceContainer, colors = CardDefaults.cardColors(containerColor = scheme.surfaceContainer),
modifier = modifier.width(256.dp) modifier = modifier.width(256.dp)
) { ) {
Column( Column(modifier = Modifier.fillMaxWidth()) {
modifier = Modifier
.fillMaxWidth()
.clickable { onMediaSelected(uiModel) }
) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@@ -83,7 +80,7 @@ internal fun NextUpCard(
Text( Text(
text = uiModel.secondaryText, text = uiModel.secondaryText,
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
color = scheme.onSurface, color = scheme.onSurfaceVariant,
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Ellipsis overflow = TextOverflow.Ellipsis
) )

View File

@@ -22,10 +22,11 @@ fun LibraryTopBar(
IconButton( IconButton(
onClick = onSearchClick, onClick = onSearchClick,
colors = IconButtonColors( colors = IconButtonColors(
containerColor = scheme.secondary, containerColor = scheme.surface,
contentColor = scheme.onSecondary, contentColor = scheme.onSurface,
disabledContainerColor = scheme.secondary, disabledContainerColor = scheme.surface,
disabledContentColor = scheme.onSecondary), disabledContentColor = scheme.onSurface
),
modifier = Modifier.size(50.dp), modifier = Modifier.size(50.dp),
) { ) {
Icon( Icon(

View File

@@ -45,7 +45,6 @@ internal fun MovieTopBar(
onBack: () -> Unit, onBack: () -> Unit,
modifier: Modifier = Modifier modifier: Modifier = Modifier
) { ) {
val scheme = MaterialTheme.colorScheme
Row( Row(
modifier = modifier modifier = modifier
.fillMaxWidth() .fillMaxWidth()
@@ -107,8 +106,8 @@ internal fun MovieDetails(
) )
Row() { Row() {
MediaActionButton( MediaActionButton(
backgroundColor = MaterialTheme.colorScheme.secondary, backgroundColor = MaterialTheme.colorScheme.surface,
iconColor = MaterialTheme.colorScheme.onSecondary, iconColor = MaterialTheme.colorScheme.onSurface,
icon = when (downloadState) { icon = when (downloadState) {
is DownloadState.NotDownloaded -> Icons.Outlined.Download is DownloadState.NotDownloaded -> Icons.Outlined.Download
is DownloadState.Downloading -> Icons.Outlined.Close is DownloadState.Downloading -> Icons.Outlined.Close

View File

@@ -103,7 +103,6 @@ private fun SeriesScreenInternal(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
val scheme = MaterialTheme.colorScheme val scheme = MaterialTheme.colorScheme
val textMutedStrong = scheme.onSurfaceVariant.copy(alpha = 0.7f)
fun getDefaultSeason() : Season { fun getDefaultSeason() : Season {
for (season in series.seasons) { for (season in series.seasons) {
@@ -162,7 +161,7 @@ private fun SeriesScreenInternal(
Spacer(modifier = Modifier.height(24.dp)) Spacer(modifier = Modifier.height(24.dp))
MediaSynopsis( MediaSynopsis(
synopsis = series.synopsis, synopsis = series.synopsis,
bodyColor = textMutedStrong, bodyColor = scheme.onSurface,
bodyFontSize = 13.sp, bodyFontSize = 13.sp,
bodyLineHeight = null, bodyLineHeight = null,
titleSpacing = 8.dp titleSpacing = 8.dp

View File

@@ -151,15 +151,15 @@ internal fun SeriesActionButtons(
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
} }
MediaActionButton( MediaActionButton(
backgroundColor = MaterialTheme.colorScheme.secondary, backgroundColor = MaterialTheme.colorScheme.surface,
iconColor = MaterialTheme.colorScheme.onSecondary, iconColor = MaterialTheme.colorScheme.onSurface,
icon = Icons.Outlined.Add, icon = Icons.Outlined.Add,
height = 48.dp height = 48.dp
) )
Spacer(modifier = Modifier.width(12.dp)) Spacer(modifier = Modifier.width(12.dp))
MediaActionButton( MediaActionButton(
backgroundColor = scheme.secondary, backgroundColor = MaterialTheme.colorScheme.surface,
iconColor = scheme.onSecondary, iconColor = MaterialTheme.colorScheme.onSurface,
icon = when { icon = when {
seriesDownloadState is DownloadState.Downloading -> Icons.Outlined.Close seriesDownloadState is DownloadState.Downloading -> Icons.Outlined.Close
seriesDownloadState is DownloadState.Downloaded -> Icons.Outlined.DownloadDone seriesDownloadState is DownloadState.Downloaded -> Icons.Outlined.DownloadDone

View File

@@ -2,21 +2,18 @@ package hu.bbara.purefin.ui.common.button
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.FilledIconButton
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.onFocusChanged import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.graphics.graphicsLayer
@@ -51,7 +48,13 @@ internal fun CircularIconButton(
label = "background" label = "background"
) )
Box( FilledIconButton(
onClick = onClick,
colors = IconButtonDefaults.filledIconButtonColors(
containerColor = backgroundColor,
contentColor = iconColor
),
shape = CircleShape,
modifier = modifier modifier = modifier
.graphicsLayer { scaleX = scale; scaleY = scale } .graphicsLayer { scaleX = scale; scaleY = scale }
.size(size) .size(size)
@@ -60,16 +63,11 @@ internal fun CircularIconButton(
color = borderColor, color = borderColor,
shape = CircleShape shape = CircleShape
) )
.clip(CircleShape)
.background(backgroundColor)
.onFocusChanged { isFocused = it.isFocused || it.hasFocus } .onFocusChanged { isFocused = it.isFocused || it.hasFocus }
.clickable { onClick() },
contentAlignment = Alignment.Center
) { ) {
Icon( Icon(
imageVector = icon, imageVector = icon,
contentDescription = contentDescription, contentDescription = contentDescription
tint = iconColor
) )
} }
} }

View File

@@ -23,8 +23,8 @@ fun MediaActionButton(
CircularIconButton( CircularIconButton(
icon = icon, icon = icon,
contentDescription = null, contentDescription = null,
containerColor = backgroundColor.copy(alpha = 0.6f), containerColor = backgroundColor,
focusedBackgroundColor = focusedBackgroundColor ?: backgroundColor.copy(alpha = 0.6f), focusedBackgroundColor = focusedBackgroundColor ?: backgroundColor,
iconColor = iconColor, iconColor = iconColor,
size = height, size = height,
onClick = onClick, onClick = onClick,