feat(settings): add the month view style picker (#38, #53)

Introduces MonthViewStyle{Paged, Continuous, Split} and the setting that
chooses it. Only Paged is wired up so far — the other two land next; this
commit is the pref, the state plumbing and the chooser.

One picker rather than two switches ("vertical scrolling" + "month with
agenda"): independent toggles would multiply into four combinations, most of
which nobody asked for. Split does not disable the Agenda view — that stays a
forward multi-day window, while the split pane lists one selected day.

The chooser lives on the Views settings screen (per-view layout belongs with
the other view configuration) and is a hand-rolled FullScreenPicker rather than
OptionPicker, which cannot render previews: the three options differ in shape,
which a word like "Continuous" does not convey. Each card carries a schematic
drawn from theme tokens, and selection reads three ways over — border weight,
container tint and a check — so it never rests on colour alone. The cards are a
selectableGroup with Role.RadioButton for screen readers.

Folded into the ViewCustomization holder, which had spare arity; the outer
settings combine is still at its five-flow limit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-20 16:45:42 +02:00
parent 498250650c
commit 7510e1f9af
8 changed files with 430 additions and 3 deletions

View File

@@ -13,6 +13,7 @@ import de.jeanlucmakiola.calendula.ui.agenda.AgendaRange
import de.jeanlucmakiola.calendula.ui.common.CalendarView
import de.jeanlucmakiola.calendula.ui.common.IMPLEMENTED_VIEWS
import de.jeanlucmakiola.calendula.ui.common.QuickSwitchConfig
import de.jeanlucmakiola.calendula.ui.month.MonthViewStyle
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.runTest
import kotlinx.datetime.DayOfWeek
@@ -125,6 +126,30 @@ class SettingsPrefsTest {
assertThat(prefs.agendaWidgetRange.first()).isEqualTo(AgendaRange.Week)
}
@Test
fun `month view style defaults to paged and round-trips`(@TempDir tempDir: Path) = runTest {
val prefs = SettingsPrefs(newDataStore(tempDir))
assertThat(prefs.monthViewStyle.first()).isEqualTo(MonthViewStyle.Paged)
prefs.setMonthViewStyle(MonthViewStyle.Split)
assertThat(prefs.monthViewStyle.first()).isEqualTo(MonthViewStyle.Split)
prefs.setMonthViewStyle(MonthViewStyle.Continuous)
assertThat(prefs.monthViewStyle.first()).isEqualTo(MonthViewStyle.Continuous)
}
@Test
fun `garbage stored month view style falls back to paged`(@TempDir tempDir: Path) = runTest {
val store = newDataStore(tempDir)
val prefs = SettingsPrefs(store)
store.updateData { p ->
val m = p.toMutablePreferences()
m[SettingsPrefs.MONTH_VIEW_STYLE_KEY] = "Carousel"
m
}
assertThat(prefs.monthViewStyle.first()).isEqualTo(MonthViewStyle.Paged)
}
@Test
fun `garbage stored enum falls back to default`(@TempDir tempDir: Path) = runTest {
val store = newDataStore(tempDir)