diff options
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, |
