fix(android,ios): the player names the episode, not its file

The header under the episode's numbering showed `Episode::detail`, which
falls back to the file name — `[Judas] Chainsaw Man - S01E01.mkv` on a
phone, where the desktop shows `Dog & Chainsaw`. It now shows the
provider's name for the episode, else the one the file name gave it, and
nothing rather than the file name: the release group's tag is no caption,
and it is what a screenshot of the player would carry away.
This commit is contained in:
nvrl committed 2026-10-29 15:44:55 +01:00
1 parent 79f0d74e1a
commit b5ba59b41d
6 files changed
+60 -4

No files matched your search

@@ -97,6 +97,7 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.WindowInsetsControllerCompat
import io.narl.protonstream.settings.SettingsStore
import io.narl.protonstream.native.NativeRuntime
import io.narl.protonstream.ui.shownName
import io.narl.protonstream.ui.theme.AccentButton
import io.narl.protonstream.ui.theme.AccentTrack
import io.narl.protonstream.ui.theme.EdgedButton
@@ -567,8 +568,11 @@ fun PlayerScreen(
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.titleMedium,
)
// The episode's name, never its file name: a release
// group's tag is no caption, and it is what a screenshot
// of the player would carry away.
Text(
listOfNotNull(title.displayName, episode.detail.takeIf(String::isNotBlank))
listOfNotNull(title.displayName, episode.shownName())
.joinToString(" • "),
color = Color.White.copy(alpha = 0.7f),
maxLines = 1,
@@ -221,6 +221,13 @@ internal fun rememberQueueReason(key: Any?): String? {
}
}
/**
* The episode's own name: the provider's, else the one the filename gave it.
* `null` rather than the filename, which is a release group's tag and the
* episode's numbering again.
*/
internal fun EpisodeRecord.shownName(): String? = providerName ?: detail.takeIf { it != name && it.isNotBlank() }
/**
* What an episode row is headed with: "1. Mother and Children".
*
@@ -229,7 +236,7 @@ internal fun rememberQueueReason(key: Any?): String? {
* of `[Group] Show - S01E01.mkv` is forty rows that differ in two characters.
*/
internal fun EpisodeRecord.heading(position: Int): String {
val named = providerName ?: detail.takeIf { it != name }
val named = shownName()
val number = number?.toInt()
return when {
named != null && number != null -> "$number. $named"
@@ -0,0 +1,24 @@
package io.narl.protonstream.ui
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import uniffi.pstr_android.EpisodeRecord
class EpisodeNameTest {
private fun episode(name: String, detail: String, providerName: String? = null) = EpisodeRecord(
shareId = "s", volumeId = "v", linkId = "l", name = name, label = "S01E01", detail = detail,
season = 1u, number = 1u, size = null, progress = null, resumeAt = null,
watched = false, offline = false, providerName = providerName, providerOverview = null, stillUrl = null,
airDate = null, lastPlayed = 0,
)
@Test
fun `the player captions an episode with its name and never its filename`() {
val file = "[Group] Show - S01E01.mkv"
assertEquals("Dog & Chainsaw", episode(file, file, providerName = "Dog & Chainsaw").shownName())
assertEquals("Winter Is Coming", episode(file, "Winter Is Coming").shownName())
assertNull(episode(file, file).shownName())
assertNull(episode(file, "").shownName())
}
}