fix(month): give every covered day's dot a place inside the bar (#53)

A multi-day event has a dot on every day it covers but only one bar, so the
dots away from its start had no counterpart. Untagged they stood still and
faded; tagged without a partner they flew in from the top of the grid.
Neither is an animation — the last commit swapped one for the other.

The expanded grid now places an invisible slice of the bar in each further
column it spans, keyed to that column's day. Every dot has a real place to
come out of and go back into, at its own column, so it drops out of the bar
above it instead of appearing from nowhere.

That makes the seating's anchored flag pointless again — every dot has a
partner now — so it and its tests come back out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 22:06:22 +02:00
parent bf38dac5d7
commit 7a05fc3ac1
3 changed files with 43 additions and 80 deletions

View File

@@ -58,7 +58,7 @@ class LaneEventsTest {
val week = rowOfJuly6(listOf(bar, meeting))
// Jul 7 is column 1 of a Monday-anchored row starting Jul 6.
assertThat(week.laneEvents(col = 1, day = LocalDate(2026, 7, 7), laneCap = 3).map { it.event })
assertThat(week.laneEvents(col = 1, day = LocalDate(2026, 7, 7), laneCap = 3))
.containsExactly(bar, meeting)
.inOrder()
}
@@ -69,7 +69,7 @@ class LaneEventsTest {
val monday = timed(LocalDate(2026, 7, 6), hour = 9, id = 2L)
val week = rowOfJuly6(listOf(bar, monday))
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3).map { it.event })
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3))
.containsExactly(monday)
}
@@ -80,48 +80,11 @@ class LaneEventsTest {
(1..3).forEach { col ->
val day = LocalDate(2026, 7, 6 + col)
assertThat(week.laneEvents(col, day, laneCap = 3).map { it.event }).containsExactly(bar)
assertThat(week.laneEvents(col, day, laneCap = 3)).containsExactly(bar)
}
assertThat(week.laneEvents(col = 4, day = LocalDate(2026, 7, 10), laneCap = 3)).isEmpty()
}
/**
* Only the day a bar is drawn from has a counterpart to morph into. Tagging
* the other days' dots too gave them a shared element with no partner and so
* no bounds to start from, and they flew in from the top of the grid.
*/
@Test
fun `only the day a multi-day bar starts on is anchored`() {
val bar = allDay(LocalDate(2026, 7, 7), LocalDate(2026, 7, 9), id = 1L)
val week = rowOfJuly6(listOf(bar))
val anchored = (1..3).map { col ->
week.laneEvents(col, LocalDate(2026, 7, 6 + col), laneCap = 3).single().anchored
}
assertThat(anchored).containsExactly(true, false, false).inOrder()
}
/** A bar carried in from the previous week restarts at column 0 of this row. */
@Test
fun `a bar continuing into the row anchors on its first day here`() {
val bar = allDay(LocalDate(2026, 7, 3), LocalDate(2026, 7, 8), id = 1L)
val week = rowOfJuly6(listOf(bar))
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3).single().anchored)
.isTrue()
assertThat(week.laneEvents(col = 1, day = LocalDate(2026, 7, 7), laneCap = 3).single().anchored)
.isFalse()
}
@Test
fun `a single-day event is always anchored on its own day`() {
val meeting = timed(LocalDate(2026, 7, 6), hour = 9, id = 1L)
val week = rowOfJuly6(listOf(meeting))
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3).single().anchored)
.isTrue()
}
/** The bug the colour-gathered dots had: one dot for two events on one calendar. */
@Test
fun `events sharing a colour each keep their own lane`() {
@@ -129,7 +92,7 @@ class LaneEventsTest {
val second = timed(LocalDate(2026, 7, 6), hour = 14, id = 2L, color = RED)
val week = rowOfJuly6(listOf(first, second))
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3).map { it.event })
assertThat(week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3))
.containsExactly(first, second)
.inOrder()
}
@@ -141,7 +104,7 @@ class LaneEventsTest {
val seated = week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3)
assertThat(seated).hasSize(3)
assertThat(seated.map { it.event }).containsExactlyElementsIn(events.take(3)).inOrder()
assertThat(seated).containsExactlyElementsIn(events.take(3)).inOrder()
assertThat(week.countByDay[LocalDate(2026, 7, 6)]!! - seated.size).isEqualTo(2)
}
@@ -156,7 +119,7 @@ class LaneEventsTest {
val seated = week.laneEvents(col = 0, day = LocalDate(2026, 7, 6), laneCap = 3)
assertThat(seated).hasSize(3)
assertThat(week.spans.filter { it.lane >= 3 }.map { it.event })
.containsNoneIn(seated.map { it.event })
.containsNoneIn(seated)
}
private companion object {