Better indicators

This commit is contained in:
Damontecres 2026-01-06 15:28:15 -05:00
parent ee640f82db
commit f89eec622a
No known key found for this signature in database
4 changed files with 170 additions and 48 deletions

View file

@ -21,8 +21,7 @@ val LocalImageUrlService =
/**
* Colors not associated with the theme
*/
sealed class AppColors private constructor() {
companion object {
object AppColors {
val TransparentBlack25 = Color(0x40000000)
val TransparentBlack50 = Color(0x80000000)
val TransparentBlack75 = Color(0xBF000000)
@ -33,6 +32,12 @@ sealed class AppColors private constructor() {
val DarkPurple = Color(0xFF261370)
val GoldenYellow = Color(0xFFDAB440)
object Discover {
val Blue = Color(37, 99, 235)
val Purple = Color(147, 51, 234)
val Green = Color(74, 222, 128)
val Yellow = Color(234, 179, 8)
}
}

View file

@ -2,6 +2,7 @@ package com.github.damontecres.wholphin.ui.cards
import androidx.compose.animation.core.animateDpAsState
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsFocusedAsState
import androidx.compose.foundation.layout.Arrangement
@ -24,20 +25,27 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.tv.material3.Card
import androidx.tv.material3.CardDefaults
import androidx.tv.material3.MaterialTheme
import androidx.tv.material3.Text
import com.github.damontecres.wholphin.R
import com.github.damontecres.wholphin.data.model.DiscoverItem
import com.github.damontecres.wholphin.data.model.SeerrAvailability
import com.github.damontecres.wholphin.data.model.SeerrItemType
import com.github.damontecres.wholphin.ui.AppColors
import com.github.damontecres.wholphin.ui.AspectRatios
import com.github.damontecres.wholphin.ui.Cards
import com.github.damontecres.wholphin.ui.FontAwesome
import com.github.damontecres.wholphin.ui.PreviewTvSpec
import com.github.damontecres.wholphin.ui.enableMarquee
import com.github.damontecres.wholphin.ui.theme.WholphinTheme
import kotlinx.coroutines.delay
@Composable
@ -106,49 +114,50 @@ fun DiscoverItemCard(
Modifier
.fillMaxSize(),
)
val availabilityColor =
when (item?.availability) {
SeerrAvailability.PENDING,
SeerrAvailability.PROCESSING,
-> Color.Yellow
SeerrAvailability.PARTIALLY_AVAILABLE,
SeerrAvailability.AVAILABLE,
-> Color.Green
else -> null
-> {
PendingIndicator(Modifier.align(Alignment.TopEnd))
}
availabilityColor?.let {
Box(
modifier =
Modifier
.padding(4.dp)
.background(
color = it,
shape = CircleShape,
).size(12.dp)
.align(Alignment.TopEnd),
)
SeerrAvailability.PARTIALLY_AVAILABLE -> {
PartiallyAvailableIndicator(Modifier.align(Alignment.TopEnd))
}
SeerrAvailability.AVAILABLE,
-> {
AvailableIndicator(Modifier.align(Alignment.TopEnd))
}
else -> {}
}
if (showOverlay) {
// TODO better colors
val color =
remember(item?.type) {
when (item?.type) {
SeerrItemType.MOVIE -> Color.Blue
SeerrItemType.TV -> Color.Red
SeerrItemType.PERSON -> Color.Green
SeerrItemType.MOVIE -> AppColors.Discover.Blue
SeerrItemType.TV -> AppColors.Discover.Purple
SeerrItemType.PERSON -> AppColors.Discover.Green
SeerrItemType.UNKNOWN -> Color.Black
null -> Color.Black
}.copy(alpha = .5f)
}.copy(alpha = .8f)
}
val text =
remember(item?.type) {
when (item?.type) {
SeerrItemType.MOVIE -> R.string.movies
SeerrItemType.TV -> R.string.tv_shows
SeerrItemType.PERSON -> R.string.people
SeerrItemType.MOVIE -> R.plurals.movies
SeerrItemType.TV -> R.plurals.tv_shows
SeerrItemType.PERSON -> R.plurals.people
SeerrItemType.UNKNOWN -> null
null -> null
}?.let {
}
}
text?.let {
Text(
text = stringResource(it),
text = pluralStringResource(it, 1),
style = MaterialTheme.typography.bodySmall,
fontSize = 10.sp,
modifier =
Modifier
.align(Alignment.TopStart)
@ -192,3 +201,93 @@ fun DiscoverItemCard(
}
}
}
@Composable
fun PendingIndicator(modifier: Modifier = Modifier) {
Box(
modifier =
modifier
.padding(4.dp)
.border(
width = .5.dp,
color = AppColors.Discover.Yellow,
shape = CircleShape,
).background(
color = Color.White.copy(alpha = .85f),
shape = CircleShape,
).size(16.dp),
) {
Text(
text = stringResource(R.string.fa_bell),
fontFamily = FontAwesome,
fontSize = 10.sp,
color = AppColors.Discover.Yellow,
modifier = Modifier.align(Alignment.Center),
)
}
}
@Composable
fun AvailableIndicator(modifier: Modifier = Modifier) {
Box(
modifier =
modifier
.padding(4.dp)
.border(
width = .5.dp,
color = Color.White,
shape = CircleShape,
).background(
color = AppColors.Discover.Green.copy(alpha = .85f),
shape = CircleShape,
).size(16.dp),
) {
Text(
text = stringResource(R.string.fa_check),
fontFamily = FontAwesome,
fontSize = 10.sp,
color = Color.White,
modifier = Modifier.align(Alignment.Center),
)
}
}
@Composable
fun PartiallyAvailableIndicator(modifier: Modifier = Modifier) {
Box(
modifier =
modifier
.padding(4.dp)
.border(
width = .5.dp,
color = Color.White,
shape = CircleShape,
).background(
color = AppColors.Discover.Green.copy(alpha = .85f),
shape = CircleShape,
).size(16.dp),
) {
Box(
modifier =
Modifier
.align(Alignment.Center)
.size(width = 10.dp, height = 2.dp)
.background(
color = Color.White,
shape = CircleShape,
),
)
}
}
@PreviewTvSpec
@Composable
private fun Preview() {
WholphinTheme {
Column {
PendingIndicator()
AvailableIndicator()
PartiallyAvailableIndicator()
}
}
}

View file

@ -47,4 +47,6 @@
<string name="fa_sliders" translatable="false">&#xf1de;</string>
<string name="fa_download" translatable="false">&#xf019;</string>
<string name="fa_clock" translatable="false">&#xf017;</string>
<string name="fa_bell" translatable="false">&#xf0f3;</string>
<string name="fa_check" translatable="false">&#xf00c;</string>
</resources>

View file

@ -252,6 +252,22 @@
<item quantity="other">%d seconds</item>
</plurals>
<plurals name="movies">
<item quantity="zero">Movies</item>
<item quantity="one">Movie</item>
<item quantity="other">Movies</item>
</plurals>
<plurals name="tv_shows">
<item quantity="zero">TV Shows</item>
<item quantity="one">TV Show</item>
<item quantity="other">TV Shows</item>
</plurals>
<plurals name="people">
<item quantity="zero">People</item>
<item quantity="one">Person</item>
<item quantity="other">People</item>
</plurals>
<!-- Preferences/Setting specific strings -->
<string name="pref_key_update_last_check_threshold" translatable="false">preference.update.threshold</string>
<string name="pref_key_update_last_check" translatable="false">preference.update.lastTimestamp</string>