Fix showing live tv programs on home page (#1504)

## Description
Fixes the inconsistent live tv programs shown on the home page by using
a different API endpoint & filtering.

Also some UI fixes:
- Use the "Watch live" string consistently for the row instead of it
sometimes switching to "Live TV"
- Adjust the "Ends at" in the home page header to show the actual end
time
- Show the channel name in "quick details"
- Show season & episode number, if applicable, in "quick details"

### Related issues
Fixes #1080

### Testing
Nvidia shield w/ fake EPG data

## Screenshots
N/A, just UI fixes, nothing new

## AI or LLM usage
None
This commit is contained in:
Damontecres 2026-06-03 12:40:53 -04:00 • committed by GitHub
parent 6c64470c28
commit 5ae452155e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 88 additions and 25 deletions

View file

@ -83,6 +83,8 @@ val PhotoItemFields =
ItemFields.HEIGHT,
)
val ProgramItemFields = DefaultItemFields + listOf(ItemFields.CHANNEL_INFO)
object Cards {
const val HEIGHT_2X3_DP = 172
val height2x3 = HEIGHT_2X3_DP.dp

View file

@ -11,7 +11,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalResources
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.AnnotatedString
@ -29,6 +28,7 @@ import com.github.damontecres.wholphin.ui.dot
import com.github.damontecres.wholphin.ui.getTimeFormatter
import com.github.damontecres.wholphin.ui.util.LocalClock
import com.github.damontecres.wholphin.ui.util.LocalInterfaceCustomization
import org.jellyfin.sdk.model.DateTime
import kotlin.time.Duration
@Composable
@ -37,6 +37,7 @@ fun QuickDetails(
timeRemaining: Duration?,
modifier: Modifier = Modifier,
textStyle: TextStyle = MaterialTheme.typography.titleSmall,
endsAt: DateTime? = null,
) {
val enabled = LocalInterfaceCustomization.current.enabledDisplayToggles
val inlineContentMap = rememberQuickDetailsContentMap(textStyle)
@ -53,7 +54,11 @@ fun QuickDetails(
QuickDetailsText(details.criticRating, Modifier, textStyle, inlineContentMap)
}
}
timeRemaining?.let { TimeRemaining(it, textStyle = textStyle) }
if (timeRemaining != null) {
TimeRemaining(timeRemaining, textStyle = textStyle)
} else if (endsAt != null) {
EndsAt(endsAt, textStyle = textStyle)
}
}
}
@ -150,3 +155,26 @@ fun TimeRemaining(
modifier = modifier,
)
}
@Composable
fun EndsAt(
endsAt: DateTime,
modifier: Modifier = Modifier,
textStyle: TextStyle = MaterialTheme.typography.titleSmall,
) {
val resources = LocalResources.current
val remainingStr =
remember(endsAt, resources) {
val endTimeStr = getTimeFormatter().format(endsAt)
buildAnnotatedString {
dot()
append(resources.getString(R.string.ends_at, endTimeStr))
}
}
Text(
text = remainingStr,
style = textStyle,
maxLines = 1,
modifier = modifier,
)
}

View file

@ -300,6 +300,7 @@ fun SeerrDiscoverPage(
overviewTwoLines = true,
quickDetails = details,
timeRemaining = null,
endsAt = null,
showLogo = preferences.appPreferences.interfacePreferences.showLogos,
logoImageUrl = null, // TODO
modifier =

View file

@ -88,6 +88,7 @@ import com.github.damontecres.wholphin.ui.util.ScrollToTopBringIntoViewSpec
import com.github.damontecres.wholphin.util.HomeRowLoadingState
import com.github.damontecres.wholphin.util.LoadingState
import kotlinx.coroutines.delay
import org.jellyfin.sdk.model.DateTime
import org.jellyfin.sdk.model.api.BaseItemKind
import org.jellyfin.sdk.model.api.MediaType
import timber.log.Timber
@ -550,6 +551,7 @@ fun HomePageHeader(
overviewTwoLines = isEpisode,
quickDetails = item?.ui?.quickDetails,
timeRemaining = item?.timeRemainingOrRuntime,
endsAt = item?.data?.endDate,
showLogo = showLogo,
logoImageUrl = rememberLogoUrl(item),
modifier = modifier,
@ -564,6 +566,7 @@ fun HomePageHeader(
overviewTwoLines: Boolean,
quickDetails: QuickDetailsData?,
timeRemaining: Duration?,
endsAt: DateTime?,
showLogo: Boolean,
logoImageUrl: String?,
modifier: Modifier = Modifier,
@ -587,7 +590,7 @@ fun HomePageHeader(
if (subtitle != null) {
EpisodeName(subtitle)
}
QuickDetails(quickDetails, timeRemaining)
QuickDetails(quickDetails, timeRemaining, endsAt = endsAt)
val overviewModifier =
Modifier
.padding(0.dp)

View file

@ -136,7 +136,7 @@ enum class LibraryRowType(
GENRES(R.string.genres),
STUDIOS(R.string.studios),
TV_CHANNELS(R.string.channels),
TV_PROGRAMS(R.string.live_tv),
TV_PROGRAMS(R.string.watch_live),
RECENTLY_RECORDED(R.string.recently_recorded),
COLLECTION(R.string.collection),
PLAYLIST(R.string.playlist),