fix(month): carry the scroll position across a style change (#38)
All checks were successful
Translations / check (pull_request) Successful in 5s
CI / ci (pull_request) Successful in 5m54s

The scrolling styles navigate by scroll position and never set the paged
month, so it sat wherever paged navigation last left it — today's month
on a fresh open. Switching to a paged style, or reseeding the other
scrolling style's list state (both read off it), snapped back there
instead of holding the month on screen.

Track the paged month to the visible month while a scrolling style is
up, realigning the split selection alongside it so landing on Split
shows a live day in the month you were viewing rather than a stale,
off-month one.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 23:20:34 +02:00
parent 28fb7404d8
commit 052335e842
2 changed files with 28 additions and 0 deletions

View File

@@ -239,6 +239,19 @@ fun MonthScreen(
.collect { (first, last) -> viewModel.onVisibleMonthsChanged(first, last) }
}
// Keep the paged month tracking the scrolling grid. The scrolling styles
// navigate by scroll position and never touch the paged month otherwise, so
// without this it stays wherever paged navigation last left it (today's
// month, on a fresh open) — and switching to a paged style, or reseeding the
// other scrolling style's list state, which both read off it, would snap
// back there rather than staying on the month you were looking at.
LaunchedEffect(listState, scrolling, dense, weekStart) {
if (!scrolling) return@LaunchedEffect
snapshotFlow { visibleMonth }
.distinctUntilChanged()
.collect { viewModel.syncScrollMonth(it) }
}
val isOnCurrentMonth = titleMonth == YearMonth(today.year, today.month)
// Continuous names the month on the block's own sticky header, so the bar

View File

@@ -284,6 +284,21 @@ class MonthViewModel @Inject constructor(
_selectedDate.value = todayDate
}
/**
* Track [_month] to the month a scrolling style is showing. Those styles
* navigate by scroll position and never set [_month] themselves, so it would
* otherwise sit wherever paged navigation last left it (today's month, on a
* fresh open) — and a switch to a paged style, or a reseed of the other
* scrolling style's list, would jump there instead of holding position. The
* selection is realigned alongside it so that landing on the Split style
* shows a live day in the month on screen rather than a stale, off-month one.
*/
fun syncScrollMonth(ym: YearMonth) {
if (_month.value == ym) return
_month.value = ym
_selectedDate.value = selectionForMonth(ym, todayDate)
}
/** Jump to the month containing [date] (drawer jump-to-date). */
fun goToDate(date: LocalDate) {
_month.value = YearMonth(date.year, date.month)