diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-11-02 07:48:34 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-11-02 07:48:34 +0000 |
| commit | b9b91ba21c5a2d333b45d8c1c73ea77c6d1cd3b9 (patch) | |
| tree | e2e45395acf914db46b710f53cf9e920c2e35977 /app/src | |
| parent | 2cc252a27a2b1ec801522e942d255ca9a9b95392 (diff) | |
The empty queue says it is empty, and Up Next is one name
Two things found by walking the queue screen, which was the one screen the UI pass had not
reached.
It was the only list in the app that went blank. Every other one explains itself when there is
nothing to show -- EmptyLibrary, EmptyBedtime, EmptyRules, the chapter list, the transcript -- but
removing the last episode from the queue left a back arrow, a title and nothing, which reads as a
screen that failed rather than one with nothing in it. Worse, the empty queue screen is only
reachable *by* emptying it: with nothing queued the library hides its Up Next heading and the
now-playing bar is absent, so there is no way in. Blank was therefore the only state that screen
ever showed after the last removal.
It now names the state and says where episodes come from, since none of the three ways in are on
that screen. Test written first and watched failing on the missing text, not on a compile error,
then confirmed green; then read back off the emulator by queueing an episode, opening the queue
and removing it.
The second is wording. The queue is called "Up Next" in the Android Auto browse tree, in the queue
screen's title, in the now-playing bar's icon and in the banner after queueing something -- and
"Up next" in the library heading directly above the row it describes. One name.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018AwnALZL6bD4VBtATDVv3B
Diffstat (limited to 'app/src')
3 files changed, 66 insertions, 1 deletions
diff --git a/app/src/androidTest/java/org/terst/listen/ui/EmptyQueueTest.kt b/app/src/androidTest/java/org/terst/listen/ui/EmptyQueueTest.kt new file mode 100644 index 0000000..3641939 --- /dev/null +++ b/app/src/androidTest/java/org/terst/listen/ui/EmptyQueueTest.kt @@ -0,0 +1,38 @@ +package org.terst.listen.ui + +import androidx.compose.ui.test.assertIsDisplayed +import androidx.compose.ui.test.junit4.createComposeRule +import androidx.compose.ui.test.onNodeWithText +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * What the queue screen says when the queue is empty. + * + * It said nothing at all until now -- the one list screen in the app without an empty state, so + * removing the last episode left a bar, a title and a blank page. Pinned as a test because the + * failure is silent: a screen that renders nothing looks the same as a screen that crashed. + */ +@RunWith(AndroidJUnit4::class) +class EmptyQueueTest { + + @get:Rule + val compose = createComposeRule() + + @Test + fun itNamesTheStateRatherThanLeavingTheScreenBlank() { + compose.setContent { EmptyQueue() } + + compose.onNodeWithText("Nothing queued").assertIsDisplayed() + } + + /** The queue is filled from elsewhere, so the empty state has to say from where. */ + @Test + fun itSaysWhereEpisodesComeFrom() { + compose.setContent { EmptyQueue() } + + compose.onNodeWithText("Queue", substring = true).assertIsDisplayed() + } +} diff --git a/app/src/main/java/org/terst/listen/ui/LibraryScreen.kt b/app/src/main/java/org/terst/listen/ui/LibraryScreen.kt index a926ce6..bc0e6fc 100644 --- a/app/src/main/java/org/terst/listen/ui/LibraryScreen.kt +++ b/app/src/main/java/org/terst/listen/ui/LibraryScreen.kt @@ -195,7 +195,7 @@ internal fun LibraryList( val bedtime = content.bedtime LazyColumn(Modifier.fillMaxSize()) { if (queue.isNotEmpty()) { - item { SectionHeading("Up next \u00b7 ${queue.size}") } + item { SectionHeading("Up Next \u00b7 ${queue.size}") } item { UpNextRow(queue.first(), onOpenQueue) } } if (subscriptions.isEmpty()) { diff --git a/app/src/main/java/org/terst/listen/ui/QueueScreen.kt b/app/src/main/java/org/terst/listen/ui/QueueScreen.kt index 119f6ee..4665132 100644 --- a/app/src/main/java/org/terst/listen/ui/QueueScreen.kt +++ b/app/src/main/java/org/terst/listen/ui/QueueScreen.kt @@ -2,6 +2,7 @@ package org.terst.listen.ui import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -77,6 +78,10 @@ fun QueueScreen(vm: ListenViewModel, player: PlayerViewModel, nav: QueueNav) { }, bottomBar = { PlayerBar(player, nav.openEpisode, nav.openQueue) }, ) { padding -> + if (localOrder.isEmpty()) { + EmptyQueue(Modifier.padding(padding)) + return@Scaffold + } LazyColumn(state = lazyListState, modifier = Modifier.padding(padding).fillMaxSize()) { items(localOrder, key = { it.id }) { episode -> ReorderableItem(reorderableState, key = episode.id) { @@ -97,6 +102,28 @@ fun QueueScreen(vm: ListenViewModel, player: PlayerViewModel, nav: QueueNav) { } } +/** + * What the screen says with nothing in it. + * + * The queue was the one list in the app that went blank instead -- a bar, a title and nothing, + * which reads as a screen that failed rather than one with nothing to show. Says where episodes + * come from, because none of the three ways in are on this screen. + */ +@Composable +internal fun EmptyQueue(modifier: Modifier = Modifier) { + Column( + modifier.fillMaxSize().padding(24.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + ) { + Text("Nothing queued", style = MaterialTheme.typography.titleMedium) + Text( + "Queue an episode from a show's list or the library. Rules and slow-drip releases " + + "add to it too, and anything you play goes to the top.", + style = MaterialTheme.typography.bodyMedium, + ) + } +} + @Composable private fun ReorderableCollectionItemScope.QueueRow( episode: EpisodeEntity, |
