summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
Diffstat (limited to 'app')
-rw-r--r--app/src/main/java/org/terst/listen/ui/DescriptionPreview.kt22
-rw-r--r--app/src/main/java/org/terst/listen/ui/EpisodeDescription.kt4
-rw-r--r--app/src/test/java/org/terst/listen/ui/DescriptionPreviewTest.kt33
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)
}