diff --git a/android/app/src/main/java/tv/orbit/classic/ClassicProgrammeStrip.kt b/android/app/src/main/java/tv/orbit/classic/ClassicProgrammeStrip.kt index 7d8ad8b..cb59229 100644 --- a/android/app/src/main/java/tv/orbit/classic/ClassicProgrammeStrip.kt +++ b/android/app/src/main/java/tv/orbit/classic/ClassicProgrammeStrip.kt @@ -42,12 +42,14 @@ internal fun ClassicProgrammeStrip(item: SampleItem, playing: Boolean, modifier: val catching = scheduled?.catchingUp() == true Text(if (catching) (if (playing) "FROM START" else "PAUSED") else if (playing || scheduled != null) "NOW" else "PAUSED", Modifier.background(Yellow, RoundedCornerShape(4.dp)).padding(horizontal = 7.dp, vertical = 2.dp), color = OnAccent, fontWeight = FontWeight.Bold, fontSize = 13.sp) - Text(" " + item.title, Modifier.weight(1f, fill = false), color = Ink, fontWeight = FontWeight.Bold, fontSize = 20.sp, maxLines = 1, overflow = TextOverflow.Ellipsis) - // A short in a slot says where it sits: "Cartoon Shorts · 3 of 6" (Paul, 6 November 2026). - scheduled?.let { shortsLine(it.channel, it.programme) }?.let { line -> - Text(" $line", color = Muted, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, maxLines = 1) + // The title takes the room, so the times sit at the right end, under the clock (Paul, 6 November 2026). + Row(Modifier.weight(1f), verticalAlignment = Alignment.CenterVertically) { + Text(" " + item.title, Modifier.weight(1f, fill = false), color = Ink, fontWeight = FontWeight.Bold, fontSize = 20.sp, maxLines = 1, overflow = TextOverflow.Ellipsis) + // A short in a slot says where it sits: "Cartoon Shorts · 3 of 6" (Paul, 6 November 2026). + scheduled?.let { shortsLine(it.channel, it.programme) }?.let { line -> + Text(" $line", color = Muted, fontWeight = FontWeight.SemiBold, fontSize = 14.sp, maxLines = 1) + } } - Spacer(Modifier.weight(1f)) scheduled?.takeIf { !it.catchingUp() }?.let { Text("${clock(it.programme.startMs)} to ${clock(it.next.startMs)}", color = Muted, fontSize = 13.sp) } } // How far through: the accent along a track of the raised colour. diff --git a/android/app/src/main/java/tv/orbit/classic/EmbyPlaybackDialog.kt b/android/app/src/main/java/tv/orbit/classic/EmbyPlaybackDialog.kt index d71615b..2900871 100644 --- a/android/app/src/main/java/tv/orbit/classic/EmbyPlaybackDialog.kt +++ b/android/app/src/main/java/tv/orbit/classic/EmbyPlaybackDialog.kt @@ -491,8 +491,15 @@ internal fun EmbyPlaybackDialog(session: EmbySampleSession, plan: EmbyPlaybackPl // The bar and the subtitles and sound panel together (design/watching): the panel docks above the bar's right // end, so it never hangs over it, and the bar stays while the panel is open. val barUp = (infoVisible || trackMenu != null) && failure == null && ready && squeeze == 0f - if (barUp || trackMenu != null) Column(Modifier.align(Alignment.BottomCenter).fillMaxWidth(.86f).padding(bottom = 26.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { - trackMenu?.let { Box(Modifier.fillMaxWidth()) { TrackPanel(it, trackCursor, Modifier.align(Alignment.BottomEnd)) } } + if (barUp || trackMenu != null) Column(Modifier.align(Alignment.BottomCenter).fillMaxWidth(.86f).padding(top = 24.dp, bottom = 26.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) { + // The bar is measured first; the panel gets the room above it and shows as many rows as fit there, so a long + // list never pushes the bar off the screen (Paul, 6 November 2026). + trackMenu?.let { rows -> + BoxWithConstraints(Modifier.fillMaxWidth().weight(1f, fill = false)) { + val fits = ((maxHeight - 56.dp) / 34.dp).toInt().coerceIn(3, 12) + TrackPanel(rows, trackCursor, Modifier.align(Alignment.BottomEnd), maxRows = fits) + } + } if (barUp) ClassicProgrammeStrip(plan.item, playing, Modifier.fillMaxWidth(), scheduled = scheduled, panelOpen = trackMenu != null) } ident?.invoke() diff --git a/android/app/src/main/java/tv/orbit/classic/WatchingControls.kt b/android/app/src/main/java/tv/orbit/classic/WatchingControls.kt index 7061922..ed16801 100644 --- a/android/app/src/main/java/tv/orbit/classic/WatchingControls.kt +++ b/android/app/src/main/java/tv/orbit/classic/WatchingControls.kt @@ -91,15 +91,15 @@ private const val TRACK_PANEL_ROWS = 12 /** Sits to one side, so the programme keeps playing while you choose. */ @Composable -internal fun TrackPanel(rows: List, cursor: Int, modifier: Modifier = Modifier) { +internal fun TrackPanel(rows: List, cursor: Int, modifier: Modifier = Modifier, maxRows: Int = TRACK_PANEL_ROWS) { // The same card as the programme bar, in the look's own colours (design/watching); the bar below carries the buttons. val corner = RoundedCornerShape(8.dp) // Subtitles, sound and the sleep timer can be more than the screen holds, so it shows a stretch around the cursor. - val first = (cursor - TRACK_PANEL_ROWS / 2).coerceIn(0, (rows.size - TRACK_PANEL_ROWS).coerceAtLeast(0)) + val first = (cursor - maxRows / 2).coerceIn(0, (rows.size - maxRows).coerceAtLeast(0)) Column(modifier.width(300.dp).background(Deep.copy(alpha = .96f), corner).border(1.dp, Blue, corner).padding(10.dp), verticalArrangement = Arrangement.spacedBy(3.dp)) { if (first > 0) Text("▲ more", color = Muted, fontSize = 11.sp, modifier = Modifier.padding(start = 8.dp)) rows.forEachIndexed { index, row -> - if (index < first || index >= first + TRACK_PANEL_ROWS) return@forEachIndexed + if (index < first || index >= first + maxRows) return@forEachIndexed if (index == first || rows[index - 1].section != row.section) { if (index != first) Box(Modifier.padding(horizontal = 8.dp, vertical = 4.dp).fillMaxWidth().height(1.dp).background(Blue)) Text(row.section.uppercase(), color = Muted, fontSize = 12.sp, fontWeight = FontWeight.Bold, letterSpacing = 2.sp, modifier = Modifier.padding(start = 8.dp, top = 2.dp)) @@ -108,6 +108,6 @@ internal fun TrackPanel(rows: List, cursor: Int, modifier: Modifier = Text((if (row.selected) "✓ " else " ") + row.label, Modifier.fillMaxWidth().background(if (on) Yellow else Color.Transparent, RoundedCornerShape(6.dp)).padding(horizontal = 10.dp, vertical = 4.dp), color = if (on) OnAccent else Ink, fontSize = 15.sp, fontWeight = if (on || row.selected) FontWeight.SemiBold else FontWeight.Normal, maxLines = 1) } - if (first + TRACK_PANEL_ROWS < rows.size) Text("▼ more", color = Muted, fontSize = 11.sp, modifier = Modifier.padding(start = 8.dp)) + if (first + maxRows < rows.size) Text("▼ more", color = Muted, fontSize = 11.sp, modifier = Modifier.padding(start = 8.dp)) } }