diff options
Diffstat (limited to 'app')
3 files changed, 46 insertions, 13 deletions
diff --git a/app/src/main/java/org/terst/listen/ui/DescriptionPreview.kt b/app/src/main/java/org/terst/listen/ui/DescriptionPreview.kt index 2569408..667a4db 100644 --- a/app/src/main/java/org/terst/listen/ui/DescriptionPreview.kt +++ b/app/src/main/java/org/terst/listen/ui/DescriptionPreview.kt @@ -3,16 +3,26 @@ package org.terst.listen.ui /** * How much of a description shows before the listener asks for the rest. * - * A show with long notes used to push the transport off the screen, so the notes start as about - * two lines. The rule is line count *and* a character budget: stripped HTML is often one long - * paragraph, which two newline-delimited lines would not limit at all. + * It used to be two lines, because a show with long notes pushed the transport off the screen. + * That reason is gone: when the player and the episode screen merged, the notes moved *below* + * the transport, so there is nothing underneath them left to push away. What the old limit + * actually did on a real episode was cut the notes at 140 characters and leave the bottom + * three-fifths of the screen empty. + * + * So the budget is now what the space will hold -- about ten lines on a phone, measured against + * the gap the old rule left behind -- and the tap still opens the rest for notes longer than + * that. The rule is line count *and* a character budget, because stripped HTML is often one + * long paragraph that no number of newline-delimited lines would limit at all. */ object DescriptionPreview { - private const val MAX_LINES = 2 + /** Shared with the Text that renders it, so the two cannot disagree about the cut. */ + const val PREVIEW_LINES = 10 + + private const val MAX_LINES = PREVIEW_LINES - /** Roughly two lines of body text on a phone. */ - const val MAX_CHARS = 140 + /** Roughly ten lines of body text on a phone. */ + const val MAX_CHARS = 700 private const val ELLIPSIS = "…" diff --git a/app/src/main/java/org/terst/listen/ui/EpisodeDescription.kt b/app/src/main/java/org/terst/listen/ui/EpisodeDescription.kt index a3d9ea3..90dc78e 100644 --- a/app/src/main/java/org/terst/listen/ui/EpisodeDescription.kt +++ b/app/src/main/java/org/terst/listen/ui/EpisodeDescription.kt @@ -11,7 +11,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.text.style.TextOverflow -/** About two lines of the notes; a tap shows the rest, and another tap folds it back. */ +/** As much of the notes as the screen holds; a tap shows the rest, and another folds it back. */ @Composable fun ExpandableDescription(text: String) { val preview = DescriptionPreview.collapse(text) @@ -20,7 +20,7 @@ fun ExpandableDescription(text: String) { Text( if (showAll) text else preview.text, style = MaterialTheme.typography.bodyMedium, - maxLines = if (showAll) Int.MAX_VALUE else 2, + maxLines = if (showAll) Int.MAX_VALUE else DescriptionPreview.PREVIEW_LINES, overflow = TextOverflow.Ellipsis, modifier = if (preview.truncated) Modifier.clickable { expanded = !expanded } else Modifier, ) diff --git a/app/src/test/java/org/terst/listen/ui/DescriptionPreviewTest.kt b/app/src/test/java/org/terst/listen/ui/DescriptionPreviewTest.kt index 6e9d9c1..4a61403 100644 --- a/app/src/test/java/org/terst/listen/ui/DescriptionPreviewTest.kt +++ b/app/src/test/java/org/terst/listen/ui/DescriptionPreviewTest.kt @@ -5,8 +5,23 @@ import org.junit.Assert.assertFalse import org.junit.Assert.assertTrue import org.junit.Test +/** + * How much of an episode's notes shows before the listener asks for the rest. + * + * The fixtures are sized from the constants rather than written out, because they were not: the + * budget went from two lines to ten when the transport moved above the notes, and three tests + * that were really about "more than the budget is cut" had the old budget baked into their + * text. + */ class DescriptionPreviewTest { + /** One line more than fits, so the cut is exercised whatever the budget becomes. */ + private fun linesBeyondTheBudget(): String = + (1..DescriptionPreview.PREVIEW_LINES + 1).joinToString("\n") { "Line $it." } + + private fun keptLines(): String = + (1..DescriptionPreview.PREVIEW_LINES).joinToString("\n") { "Line $it." } + @Test fun `a short description is shown whole`() { val p = DescriptionPreview.collapse("A short note.") @@ -22,12 +37,20 @@ class DescriptionPreviewTest { } @Test - fun `a third line is cut and the rest is offered`() { - val p = DescriptionPreview.collapse("First.\nSecond.\nThird.") - assertEquals("First.\nSecond.…", p.text) + fun `a line beyond the budget is cut and the rest is offered`() { + val p = DescriptionPreview.collapse(linesBeyondTheBudget()) + assertEquals(keptLines() + "…", p.text) assertTrue(p.truncated) } + /** Everything within the budget is shown, which is the case the old two-line rule failed. */ + @Test + fun `a description that fits the budget is shown whole`() { + val p = DescriptionPreview.collapse(keptLines()) + assertEquals(keptLines(), p.text) + assertFalse(p.truncated) + } + @Test fun `blank lines do not use up the allowance`() { val p = DescriptionPreview.collapse("First.\n\n\nSecond.") @@ -37,7 +60,7 @@ class DescriptionPreviewTest { @Test fun `one long paragraph is cut at a word boundary within the budget`() { - val long = "word ".repeat(100).trim() + val long = "word ".repeat(DescriptionPreview.MAX_CHARS).trim() val p = DescriptionPreview.collapse(long) assertTrue(p.truncated) assertTrue(p.text.endsWith("word…")) @@ -46,7 +69,7 @@ class DescriptionPreviewTest { @Test fun `an unbroken string is hard cut rather than dropped`() { - val p = DescriptionPreview.collapse("x".repeat(500)) + val p = DescriptionPreview.collapse("x".repeat(DescriptionPreview.MAX_CHARS * 2)) assertTrue(p.truncated) assertEquals(DescriptionPreview.MAX_CHARS + 1, p.text.length) } |
