Leave out a stop with nothing due

c3437b5 · Gabriel Morell · 2026-09-03 15:45

20 files +34 -25
Message
{commit_body(@commit)}

Files changed

modified clients/android/app/src/main/java/io/neiam/apolloscrib/targets/GtfsRenderer.kt
+9 −0
@@ -27,6 +27,15 @@ object GtfsRenderer : SourceRenderer {
27 27 override fun preview(entry: VisionEntry): List<Preview> {
28 28 val routes = entry.decode<List<GtfsCondensed>>().orEmpty()
29 29
30 + // A stop with nothing due is not news. Unlike a dock with no bikes --
31 + // where the count is the answer -- an empty departure board says only
32 + // that the query window is quiet, and it crowds out the stops that do
33 + // have something. An alert still shows: "suspended" is why there is
34 + // nothing due, and worth the space on its own.
35 + if (routes.all { it.times.isEmpty() }) {
36 + return listOfNotNull(alert(entry, routes))
37 + }
38 +
30 39 // Soonest first. The publisher orders departures within a route but
31 40 // says nothing about the order of the routes themselves.
32 41 val soonest = routes.sortedBy { it.departures().firstOrNull() ?: "99:99" }
modified clients/android/app/src/main/java/io/neiam/apolloscrib/ui/BoardScreen.kt
+4 −20
@@ -95,26 +95,10 @@ fun BoardScreen(
95 95 }
96 96
97 97 entries.forEach { entry ->
98 − val previews = Targets.preview(entry)
99 − if (previews.isEmpty()) {
100 − // A query this build can draw, that answered with nothing it
101 − // knows how to say. Worth showing as itself rather than as a
102 − // gap in the list.
103 − item(key = entry.key) {
104 − PreviewCard(
105 − Preview(
106 − id = entry.key,
107 − title = entry.label(),
108 − subtitle = entry.key,
109 − iconRes = io.neiam.apolloscrib.R.drawable.ic_crib,
110 − empty = "Nothing to show"
111 − )
112 − )
113 − }
114 − } else {
115 − items(previews, key = { "${entry.key}-${it.id}" }) { preview ->
116 − PreviewCard(preview)
117 − }
98 + // No preview means the renderer had nothing worth a card -- a
99 + // stop with nothing due says so by not being there.
100 + items(Targets.preview(entry), key = { "${entry.key}-${it.id}" }) { preview ->
101 + PreviewCard(preview)
118 102 }
119 103 }
120 104
modified clients/android/app/src/test/java/io/neiam/apolloscrib/targets/RendererTest.kt
+21 −5
@@ -115,14 +115,30 @@ class RendererTest {
115 115 }
116 116
117 117 @Test
118 − fun `a stop with nothing due still draws, and says so`() {
118 + fun `a stop with nothing due is not drawn at all`() {
119 + // A dock with no bikes still answers the question; an empty departure
120 + // board only says the window is quiet, and crowds out the stops that
121 + // have something.
119 122 val previews = GtfsRenderer.preview(
120 123 entry("""{"gtfs-1": {"query": {"name": "Curtis St", "meta": {}}, "data": []}}""")
121 124 )
122 − val board = previews.single()
123 − assertEquals("Curtis St", board.title)
124 − assertTrue(board.rows.isEmpty())
125 − assertEquals("Nothing due", board.empty)
125 + assertTrue(previews.isEmpty())
126 + }
127 +
128 + @Test
129 + fun `an alert still shows when there is nothing due`() {
130 + // "Suspended" is why there is nothing due, and worth the space alone.
131 + val previews = GtfsRenderer.preview(
132 + entry(
133 + """
134 + {"gtfs-1": [{"route":"RL","dest":"Alewife","dir":"NB","mode":"Subway",
135 + "times":[],
136 + "alerts":[{"effect":"NO_SERVICE","cause":"MAINTENANCE",
137 + "header":"Red Line suspended","severity":"SEVERE"}]}]}
138 + """.trimIndent()
139 + )
140 + )
141 + assertEquals("Red Line suspended", previews.single().title)
126 142 }
127 143
128 144 @Test

Parents: b9f203c