diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4b5392f..90f70fd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -38,7 +38,7 @@ val membyGatewayUrl: String = (project.findProperty("memby.gatewayUrl") as Strin val membyDiagnosticLogLevel: String = (project.findProperty("memby.diagnosticLogLevel") as String?) ?.trim()?.uppercase()?.takeIf { it in setOf("INFO", "DEBUG", "TRACE") } ?: "INFO" -val defaultVersionName = "0.3.25" +val defaultVersionName = "0.3.26" val membyVersionName: String = (project.findProperty("memby.versionName") as String?) ?.trim() diff --git a/app/glossy-m.png b/app/glossy-m.png deleted file mode 100644 index 2cb55c1..0000000 Binary files a/app/glossy-m.png and /dev/null differ diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/player/PauseMediaHero.kt b/app/src/main/java/com/ponzischeme89/memby/ui/player/PauseMediaHero.kt index 2ff550c..9fcc482 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/player/PauseMediaHero.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/player/PauseMediaHero.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.em import androidx.compose.ui.unit.sp +import androidx.tv.material3.Icon import androidx.tv.material3.Text import coil.compose.AsyncImage import coil.request.ImageRequest @@ -46,10 +47,11 @@ import com.ponzischeme89.memby.ui.TitleLogoImage import com.ponzischeme89.memby.ui.cinematicBackdropPullBack import com.ponzischeme89.memby.ui.theme.MembyAccentBright import com.ponzischeme89.memby.ui.theme.MembyCardCorner -import com.ponzischeme89.memby.ui.theme.MembyHairline +import com.ponzischeme89.memby.ui.theme.MembyIcon import com.ponzischeme89.memby.ui.theme.MembyMutedText import com.ponzischeme89.memby.ui.theme.MembyOnSurface import com.ponzischeme89.memby.ui.theme.MembySurface +import com.ponzischeme89.memby.ui.theme.mark import com.ponzischeme89.memby.ui.useTextTitleForLogo /** The already-resolved metadata needed to render a pause without doing repository work. */ @@ -172,14 +174,7 @@ private fun PauseHeroContent( modifier: Modifier = Modifier, ) { Column(modifier, verticalArrangement = Arrangement.Top) { - Text( - text = stringResource(R.string.player_paused), - color = MembyAccentBright, - fontSize = 12.sp, - lineHeight = 15.sp, - fontWeight = FontWeight.Bold, - letterSpacing = 0.18.em, - ) + PauseHeroHeading() Spacer(Modifier.height(10.dp)) PauseHeroTitle(metadata) if (metadata.isEpisode) { @@ -196,7 +191,18 @@ private fun PauseHeroContent( ) } } - Spacer(Modifier.height(if (castVisible) 12.dp else 18.dp)) + // The synopsis is pushed to the foot of the content area rather than sat directly + // under the episode line. What is paused is said once at the top — mark, heading, + // title treatment, episode — and the description is reference material somebody + // reads only if they want it, so it belongs away from that block and out of the + // artwork's middle. The cast panel takes a fixed gap instead: it is the thing being + // looked at when it is up, and anchoring it to the bottom edge would leave a hole + // where the summary had been. + if (castVisible) { + Spacer(Modifier.height(12.dp)) + } else { + Spacer(Modifier.weight(1f).heightIn(min = 18.dp)) + } Crossfade( targetState = castVisible, animationSpec = tween(PauseHeroSectionFadeMs), @@ -273,25 +279,47 @@ private fun PauseHeroSummary(metadata: PauseMediaHeroMetadata) { }, ) } - Column( + Text( + text = synopsis, + color = MembyMutedText, + fontSize = 16.sp, + lineHeight = 22.sp, + maxLines = if (metadata.isEpisode) 5 else 7, + overflow = TextOverflow.Ellipsis, modifier = Modifier.weight(1f), - verticalArrangement = Arrangement.spacedBy(12.dp), - ) { - Text( - text = synopsis, - color = MembyMutedText, - fontSize = 16.sp, - lineHeight = 22.sp, - maxLines = if (metadata.isEpisode) 5 else 7, - overflow = TextOverflow.Ellipsis, - ) - Box(Modifier.fillMaxWidth().height(1.dp).background(MembyHairline)) - Text( - text = stringResource(R.string.player_pause_resume_hint), - color = MembyOnSurface.copy(alpha = 0.76f), - fontSize = 13.sp, - ) - } + ) + } +} + +/** + * The paused mark and its heading. + * + * The word alone was one small green line in a corner, which on a still frame reads as a + * label rather than as the reason the picture has stopped — so the mark carries the state + * and the word names it. There is deliberately nothing after it: this player is driven by + * the remote's own Play/Pause key, and a screen that has to explain that is one that does + * not trust its own transport. + */ +@Composable +private fun PauseHeroHeading() { + Row( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(8.dp), + ) { + Icon( + imageVector = MembyIcon.Pause.mark, + contentDescription = null, + tint = MembyAccentBright, + modifier = Modifier.size(16.dp), + ) + Text( + text = stringResource(R.string.player_paused), + color = MembyAccentBright, + fontSize = 12.sp, + lineHeight = 15.sp, + fontWeight = FontWeight.Bold, + letterSpacing = 0.18.em, + ) } } diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackFontAwesome.kt b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackFontAwesome.kt index af4e308..5c91a12 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackFontAwesome.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackFontAwesome.kt @@ -47,6 +47,7 @@ import com.composables.icons.fontawesome.solid.Mountain import com.composables.icons.fontawesome.solid.Music import com.composables.icons.fontawesome.solid.Palette import com.composables.icons.fontawesome.solid.PhotoVideo +import com.composables.icons.fontawesome.solid.Pause import com.composables.icons.fontawesome.solid.Play import com.composables.icons.fontawesome.solid.PlayCircle import com.composables.icons.fontawesome.solid.Plus @@ -91,6 +92,7 @@ internal val fontAwesomeIconPack = MembyIconPack( MembyIcon.Event to { FontAwesome.Solid.CalendarDay }, MembyIcon.Play to { FontAwesome.Solid.Play }, MembyIcon.PlayCircle to { FontAwesome.Solid.PlayCircle }, + MembyIcon.Pause to { FontAwesome.Solid.Pause }, MembyIcon.Favourite to { FontAwesome.Solid.Heart }, MembyIcon.Bookmark to { FontAwesome.Solid.Bookmark }, MembyIcon.PlaylistAdd to { FontAwesome.Solid.PlusCircle }, diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackLucide.kt b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackLucide.kt index 61534d5..d07d666 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackLucide.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPackLucide.kt @@ -47,6 +47,7 @@ import com.composables.icons.lucide.MountainSnow import com.composables.icons.lucide.Music2 import com.composables.icons.lucide.Palette import com.composables.icons.lucide.Pin +import com.composables.icons.lucide.Pause import com.composables.icons.lucide.Play import com.composables.icons.lucide.Plus import com.composables.icons.lucide.Power @@ -93,6 +94,7 @@ internal val lucideIconPack = MembyIconPack( MembyIcon.Event to { Lucide.CalendarClock }, MembyIcon.Play to { Lucide.Play }, MembyIcon.PlayCircle to { Lucide.CirclePlay }, + MembyIcon.Pause to { Lucide.Pause }, MembyIcon.FavouriteOutline to { Lucide.Heart }, MembyIcon.BookmarkOutline to { Lucide.Bookmark }, MembyIcon.PlaylistAdd to { Lucide.ListPlus }, diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPacks.kt b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPacks.kt index 736b4df..272c701 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPacks.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIconPacks.kt @@ -55,6 +55,7 @@ import androidx.compose.material.icons.filled.NotificationsNone import androidx.compose.material.icons.filled.NotificationsOff import androidx.compose.material.icons.filled.Palette import androidx.compose.material.icons.filled.Person +import androidx.compose.material.icons.filled.Pause import androidx.compose.material.icons.filled.PlayArrow import androidx.compose.material.icons.filled.PlayCircleFilled import androidx.compose.material.icons.filled.PlaylistRemove @@ -107,6 +108,7 @@ object MaterialIconPack { MembyIcon.Event to { Icons.Default.Event }, MembyIcon.Play to { Icons.Default.PlayArrow }, MembyIcon.PlayCircle to { Icons.Default.PlayCircleFilled }, + MembyIcon.Pause to { Icons.Default.Pause }, MembyIcon.Favourite to { Icons.Default.Favorite }, MembyIcon.FavouriteOutline to { Icons.Default.FavoriteBorder }, MembyIcon.Bookmark to { Icons.Default.Bookmark }, diff --git a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIcons.kt b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIcons.kt index 35f7641..3841950 100644 --- a/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIcons.kt +++ b/app/src/main/java/com/ponzischeme89/memby/ui/theme/MembyIcons.kt @@ -37,6 +37,7 @@ enum class MembyIcon { // Playback and library actions Play, PlayCircle, + Pause, Favourite, FavouriteOutline, Bookmark, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b80a1be..3bc3497 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -16,7 +16,6 @@ NOW PLAYING PAUSED Movie poster - Press OK to resume No description is available for this title. / Loading duration…