diff options
Diffstat (limited to 'android/app')
| -rw-r--r-- | android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt | 13 | ||||
| -rw-r--r-- | android/app/src/test/java/org/terst/doot/widget/ui/DootWidgetGridTest.kt | 34 |
2 files changed, 43 insertions, 4 deletions
diff --git a/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt b/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt index ae749fb..4a352fc 100644 --- a/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt +++ b/android/app/src/main/java/org/terst/doot/widget/ui/DootWidget.kt @@ -94,8 +94,13 @@ fun WidgetRoot(items: List<WidgetItem>, now: Instant, isRefreshing: Boolean) { val scheduledEvents = allScheduled.filter { it.type != "task" || Instant.parse(it.start!!) >= now } val floating = rest.filter { it.start == null } val fragments = SlotPacker.pack(pastTasks + floating, scheduledEvents, now) - val gridStart = calcGridStart(scheduledEvents, nowZoned.hour) - val gridEnd = calcGridEnd(scheduledEvents, nowZoned.hour) + // Grid bounds must only reflect TODAY's events -- a tomorrow event's hour-of-day + // would otherwise stretch today's grid (see calcGridStart/calcGridEnd), manufacturing + // empty hour rows that push the non-scrolling TomorrowSection below the widget's + // visible area. + val todayScheduledEvents = scheduledEvents.filter { Instant.parse(it.start!!) < tomorrowStart } + val gridStart = calcGridStart(todayScheduledEvents, nowZoned.hour) + val gridEnd = calcGridEnd(todayScheduledEvents, nowZoned.hour) val tomorrowItems = scheduledEvents .filter { Instant.parse(it.start!!) >= tomorrowStart && Instant.parse(it.start!!) < tomorrowEnd } @@ -479,7 +484,7 @@ private fun hourLabel(hour: Int): String = when { else -> "${hour - 12}p" } -private fun calcGridStart(events: List<WidgetItem>, nowHour: Int): Int { +internal fun calcGridStart(events: List<WidgetItem>, nowHour: Int): Int { val earliest = events.mapNotNull { it.start } .mapNotNull { runCatching { Instant.parse(it) }.getOrNull() } .minOrNull() @@ -488,7 +493,7 @@ private fun calcGridStart(events: List<WidgetItem>, nowHour: Int): Int { return maxOf(0, minOf(earliest, nowHour) - 1) } -private fun calcGridEnd(events: List<WidgetItem>, nowHour: Int): Int { +internal fun calcGridEnd(events: List<WidgetItem>, nowHour: Int): Int { val latest = events.mapNotNull { it.end } .mapNotNull { runCatching { Instant.parse(it) }.getOrNull() } .maxOrNull() diff --git a/android/app/src/test/java/org/terst/doot/widget/ui/DootWidgetGridTest.kt b/android/app/src/test/java/org/terst/doot/widget/ui/DootWidgetGridTest.kt new file mode 100644 index 0000000..b3d8384 --- /dev/null +++ b/android/app/src/test/java/org/terst/doot/widget/ui/DootWidgetGridTest.kt @@ -0,0 +1,34 @@ +package org.terst.doot.widget.ui + +import org.junit.Assert.assertEquals +import org.junit.Test +import org.terst.doot.widget.data.WidgetItem + +class DootWidgetGridTest { + + private fun tomorrowEvent(startIso: String, endIso: String): WidgetItem = WidgetItem( + id = "tmrw", title = "Tomorrow Event", source = "calendar", type = "event", + start = startIso, end = endIso + ) + + @Test + fun `calcGridStart on an unfiltered mixed list is skewed by tomorrow's event hour`() { + // Documents why WidgetRoot MUST pre-filter to today-only events before calling + // this function: it has no date awareness, only hour-of-day. "now" is 22:00 + // today (2026-07-12); the only item is tomorrow's (2026-07-13) 10:00 event. + val mixedList = listOf(tomorrowEvent("2026-07-13T10:00:00Z", "2026-07-13T14:30:00Z")) + assertEquals(9, calcGridStart(mixedList, nowHour = 22)) + } + + @Test + fun `calcGridStart on the correctly today-filtered (empty) list falls back to nowHour`() { + val gridStart = calcGridStart(emptyList(), nowHour = 22) + assertEquals(21, gridStart) + } + + @Test + fun `calcGridEnd falls back to nowHour plus eight when no today events, capped at 23`() { + val gridEnd = calcGridEnd(emptyList(), nowHour = 22) + assertEquals(23, gridEnd) + } +} |
