refactor(agenda): one toggle for the whole range bar
All checks were successful
Translations / check (pull_request) Successful in 4s
CI / ci (pull_request) Successful in 4m43s

Consolidate the separate "range title" and "range button" settings into a
single "Range bar" toggle, now that the header and switcher live on one bar.
On by default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-27 16:25:46 +02:00
parent 6471c48528
commit 0f31981d26
9 changed files with 47 additions and 94 deletions

View File

@@ -137,22 +137,16 @@ class SettingsPrefs @Inject constructor(
store.edit { it[AGENDA_WIDGET_RANGE_KEY] = range.storageValue() } store.edit { it[AGENDA_WIDGET_RANGE_KEY] = range.storageValue() }
} }
/** Whether the agenda shows its range-header banner (v2.11). Default ON. */ /**
val agendaShowRangeBanner: Flow<Boolean> = store.data.map { prefs -> * Whether the agenda shows its top range bar — the "showing …" header and
prefs[AGENDA_SHOW_RANGE_BANNER_KEY] ?: true * the session range switcher (v2.11). Default ON.
*/
val agendaShowRangeBar: Flow<Boolean> = store.data.map { prefs ->
prefs[AGENDA_SHOW_RANGE_BAR_KEY] ?: true
} }
suspend fun setAgendaShowRangeBanner(enabled: Boolean) { suspend fun setAgendaShowRangeBar(enabled: Boolean) {
store.edit { it[AGENDA_SHOW_RANGE_BANNER_KEY] = enabled } store.edit { it[AGENDA_SHOW_RANGE_BAR_KEY] = enabled }
}
/** Whether the agenda shows the bottom-left range pill (v2.11). Default ON. */
val agendaShowRangePill: Flow<Boolean> = store.data.map { prefs ->
prefs[AGENDA_SHOW_RANGE_PILL_KEY] ?: true
}
suspend fun setAgendaShowRangePill(enabled: Boolean) {
store.edit { it[AGENDA_SHOW_RANGE_PILL_KEY] = enabled }
} }
/** /**
@@ -346,8 +340,7 @@ class SettingsPrefs @Inject constructor(
internal val WEEK_START_KEY = stringPreferencesKey("week_start") internal val WEEK_START_KEY = stringPreferencesKey("week_start")
internal val AGENDA_SCREEN_RANGE_KEY = stringPreferencesKey("agenda_screen_range") internal val AGENDA_SCREEN_RANGE_KEY = stringPreferencesKey("agenda_screen_range")
internal val AGENDA_WIDGET_RANGE_KEY = stringPreferencesKey("agenda_widget_range") internal val AGENDA_WIDGET_RANGE_KEY = stringPreferencesKey("agenda_widget_range")
internal val AGENDA_SHOW_RANGE_BANNER_KEY = booleanPreferencesKey("agenda_show_range_banner") internal val AGENDA_SHOW_RANGE_BAR_KEY = booleanPreferencesKey("agenda_show_range_bar")
internal val AGENDA_SHOW_RANGE_PILL_KEY = booleanPreferencesKey("agenda_show_range_pill")
internal val TIME_FORMAT_KEY = stringPreferencesKey("time_format") internal val TIME_FORMAT_KEY = stringPreferencesKey("time_format")
internal val SHOW_HOUR_LINES_KEY = booleanPreferencesKey("show_hour_lines") internal val SHOW_HOUR_LINES_KEY = booleanPreferencesKey("show_hour_lines")
internal val DEFAULT_VIEW_KEY = stringPreferencesKey("default_view") internal val DEFAULT_VIEW_KEY = stringPreferencesKey("default_view")

View File

@@ -155,32 +155,25 @@ fun AgendaScreen(
.padding(innerPadding), .padding(innerPadding),
) { ) {
// One bar at the top: the "showing …" header on the left and the // One bar at the top: the "showing …" header on the left and the
// session range pill on the right (each toggleable independently). // session range switcher on the right (one settings toggle).
val s = successState successState?.takeIf { it.showRangeBar }?.let { s ->
if (s != null && (s.showRangeBanner || s.showRangePill)) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(start = 28.dp, end = 16.dp, top = 8.dp, bottom = 8.dp), .padding(start = 28.dp, end = 16.dp, top = 8.dp, bottom = 8.dp),
) { ) {
if (s.showRangeBanner) { AgendaRangeBanner(
AgendaRangeBanner( range = s.range,
range = s.range, start = s.anchor,
start = s.anchor, end = s.rangeEnd,
end = s.rangeEnd, modifier = Modifier.weight(1f),
modifier = Modifier.weight(1f), )
) AgendaRangePill(
} else { range = s.range,
Spacer(Modifier.weight(1f)) isOverride = s.rangeIsOverride,
} onClick = { showRangePicker = true },
if (s.showRangePill) { )
AgendaRangePill(
range = s.range,
isOverride = s.rangeIsOverride,
onClick = { showRangePicker = true },
)
}
} }
} }
AgendaContent( AgendaContent(

View File

@@ -59,9 +59,7 @@ sealed interface AgendaUiState {
val rangeIsOverride: Boolean, val rangeIsOverride: Boolean,
/** Last day the current [range] covers (inclusive), for the range header. */ /** Last day the current [range] covers (inclusive), for the range header. */
val rangeEnd: LocalDate, val rangeEnd: LocalDate,
/** Whether to show the range header banner (settings toggle, on by default). */ /** Whether to show the top range bar — header + switcher (toggle, on by default). */
val showRangeBanner: Boolean, val showRangeBar: Boolean,
/** Whether to show the bottom-left range pill (settings toggle, on by default). */
val showRangePill: Boolean,
) : AgendaUiState ) : AgendaUiState
} }

View File

@@ -43,12 +43,11 @@ class AgendaViewModel @Inject constructor(
@IoDispatcher private val io: CoroutineDispatcher, @IoDispatcher private val io: CoroutineDispatcher,
) : ViewModel() { ) : ViewModel() {
// The saved agenda range plus the banner/pill visibility toggles. // The saved agenda range plus the range-bar visibility toggle.
private val agendaSettings = combine( private val agendaSettings = combine(
settingsPrefs.agendaScreenRange, settingsPrefs.agendaScreenRange,
settingsPrefs.agendaShowRangeBanner, settingsPrefs.agendaShowRangeBar,
settingsPrefs.agendaShowRangePill, ) { range, showBar -> AgendaSettings(range, showBar) }
) { range, showBanner, showPill -> AgendaSettings(range, showBanner, showPill) }
// First day of the week, for the calendar-aligned "this week" range. // First day of the week, for the calendar-aligned "this week" range.
private val weekStartDay = settingsPrefs.weekStart private val weekStartDay = settingsPrefs.weekStart
@@ -74,8 +73,7 @@ class AgendaViewModel @Inject constructor(
range = override ?: settings.range, range = override ?: settings.range,
rangeIsOverride = override != null && override != settings.range, rangeIsOverride = override != null && override != settings.range,
weekStart = weekStart, weekStart = weekStart,
showRangeBanner = settings.showBanner, showRangeBar = settings.showBar,
showRangePill = settings.showPill,
) )
} }
.flatMapLatest { params -> .flatMapLatest { params ->
@@ -115,8 +113,7 @@ class AgendaViewModel @Inject constructor(
private data class AgendaSettings( private data class AgendaSettings(
val range: AgendaRange, val range: AgendaRange,
val showBanner: Boolean, val showBar: Boolean,
val showPill: Boolean,
) )
private data class AgendaParams( private data class AgendaParams(
@@ -124,8 +121,7 @@ class AgendaViewModel @Inject constructor(
val range: AgendaRange, val range: AgendaRange,
val rangeIsOverride: Boolean, val rangeIsOverride: Boolean,
val weekStart: DayOfWeek, val weekStart: DayOfWeek,
val showRangeBanner: Boolean, val showRangeBar: Boolean,
val showRangePill: Boolean,
) )
private fun buildState( private fun buildState(
@@ -149,8 +145,7 @@ class AgendaViewModel @Inject constructor(
range = params.range, range = params.range,
rangeIsOverride = params.rangeIsOverride, rangeIsOverride = params.rangeIsOverride,
rangeEnd = rangeEnd, rangeEnd = rangeEnd,
showRangeBanner = params.showRangeBanner, showRangeBar = params.showRangeBar,
showRangePill = params.showRangePill,
) )
} }
} }

View File

@@ -518,28 +518,16 @@ private fun AppearanceScreen(
onClick = { showAgendaWidgetRange = true }, onClick = { showAgendaWidgetRange = true },
) )
GroupedRow( GroupedRow(
title = stringResource(R.string.settings_agenda_range_title), title = stringResource(R.string.settings_agenda_range_bar),
summary = stringResource(R.string.settings_agenda_range_title_hint), summary = stringResource(R.string.settings_agenda_range_bar_hint),
position = Position.Middle,
trailing = {
Switch(
checked = state.agendaShowRangeBanner,
onCheckedChange = viewModel::setAgendaShowRangeBanner,
)
},
onClick = { viewModel.setAgendaShowRangeBanner(!state.agendaShowRangeBanner) },
)
GroupedRow(
title = stringResource(R.string.settings_agenda_range_button),
summary = stringResource(R.string.settings_agenda_range_button_hint),
position = Position.Bottom, position = Position.Bottom,
trailing = { trailing = {
Switch( Switch(
checked = state.agendaShowRangePill, checked = state.agendaShowRangeBar,
onCheckedChange = viewModel::setAgendaShowRangePill, onCheckedChange = viewModel::setAgendaShowRangeBar,
) )
}, },
onClick = { viewModel.setAgendaShowRangePill(!state.agendaShowRangePill) }, onClick = { viewModel.setAgendaShowRangeBar(!state.agendaShowRangeBar) },
) )
} }

View File

@@ -28,10 +28,8 @@ data class SettingsUiState(
val agendaScreenRange: AgendaRange = AgendaRange.Month, val agendaScreenRange: AgendaRange = AgendaRange.Month,
/** How far ahead the agenda widget shows events (v2.11). */ /** How far ahead the agenda widget shows events (v2.11). */
val agendaWidgetRange: AgendaRange = AgendaRange.Month, val agendaWidgetRange: AgendaRange = AgendaRange.Month,
/** Whether the agenda shows its range-header banner (v2.11). */ /** Whether the agenda shows its top range bar — header + switcher (v2.11). */
val agendaShowRangeBanner: Boolean = true, val agendaShowRangeBar: Boolean = true,
/** Whether the agenda shows the bottom-left range pill (v2.11). */
val agendaShowRangePill: Boolean = true,
/** The calendar view the app opens on, and the home of the view back stack (M1). */ /** The calendar view the app opens on, and the home of the view back stack (M1). */
val defaultView: CalendarView = CalendarView.Week, val defaultView: CalendarView = CalendarView.Week,
/** Optional event-form fields shown by default (rest behind "more fields"). */ /** Optional event-form fields shown by default (rest behind "more fields"). */

View File

@@ -84,19 +84,15 @@ class SettingsViewModel @Inject constructor(
) { view, screenRange, widgetRange, timeFormat, showHourLines -> ) { view, screenRange, widgetRange, timeFormat, showHourLines ->
ViewSettings(view, screenRange, widgetRange, timeFormat, showHourLines) ViewSettings(view, screenRange, widgetRange, timeFormat, showHourLines)
}, },
combine( prefs.agendaShowRangeBar,
prefs.agendaShowRangeBanner, ) { base, defaults, overrides, views, showRangeBar ->
prefs.agendaShowRangePill,
) { banner, pill -> banner to pill },
) { base, defaults, overrides, views, agendaToggles ->
base.copy( base.copy(
defaultView = views.defaultView, defaultView = views.defaultView,
agendaScreenRange = views.agendaScreenRange, agendaScreenRange = views.agendaScreenRange,
agendaWidgetRange = views.agendaWidgetRange, agendaWidgetRange = views.agendaWidgetRange,
timeFormat = views.timeFormat, timeFormat = views.timeFormat,
showHourLines = views.showHourLines, showHourLines = views.showHourLines,
agendaShowRangeBanner = agendaToggles.first, agendaShowRangeBar = showRangeBar,
agendaShowRangePill = agendaToggles.second,
allowColorOnUnsupportedCalendars = defaults.allowColor, allowColorOnUnsupportedCalendars = defaults.allowColor,
defaultReminderMinutes = defaults.defaultReminder, defaultReminderMinutes = defaults.defaultReminder,
defaultAllDayReminderMinutes = defaults.allDayReminder, defaultAllDayReminderMinutes = defaults.allDayReminder,
@@ -154,12 +150,8 @@ class SettingsViewModel @Inject constructor(
viewModelScope.launch { prefs.setAgendaWidgetRange(range) } viewModelScope.launch { prefs.setAgendaWidgetRange(range) }
} }
fun setAgendaShowRangeBanner(enabled: Boolean) { fun setAgendaShowRangeBar(enabled: Boolean) {
viewModelScope.launch { prefs.setAgendaShowRangeBanner(enabled) } viewModelScope.launch { prefs.setAgendaShowRangeBar(enabled) }
}
fun setAgendaShowRangePill(enabled: Boolean) {
viewModelScope.launch { prefs.setAgendaShowRangePill(enabled) }
} }
fun setTimeFormat(pref: TimeFormatPref) { fun setTimeFormat(pref: TimeFormatPref) {

View File

@@ -285,10 +285,8 @@
<string name="settings_agenda_range_hint">Wie weit im Voraus die Agenda-Ansicht Termine anzeigt.</string> <string name="settings_agenda_range_hint">Wie weit im Voraus die Agenda-Ansicht Termine anzeigt.</string>
<string name="settings_agenda_widget_range">Agenda-Widget-Zeitraum</string> <string name="settings_agenda_widget_range">Agenda-Widget-Zeitraum</string>
<string name="settings_agenda_widget_range_hint">Wie weit im Voraus das Agenda-Widget auf dem Startbildschirm Termine anzeigt.</string> <string name="settings_agenda_widget_range_hint">Wie weit im Voraus das Agenda-Widget auf dem Startbildschirm Termine anzeigt.</string>
<string name="settings_agenda_range_title">Zeitraum-Titel</string> <string name="settings_agenda_range_bar">Zeitraum-Leiste</string>
<string name="settings_agenda_range_title_hint">Eine Überschrift anzeigen, die den dargestellten Zeitraum benennt</string> <string name="settings_agenda_range_bar_hint">Eine Leiste oben in der Agenda anzeigen, die den dargestellten Zeitraum benennt, mit einer Schaltfläche zum Wechseln des Zeitraums für die Sitzung</string>
<string name="settings_agenda_range_button">Zeitraum-Schaltfläche</string>
<string name="settings_agenda_range_button_hint">Eine Schaltfläche in der Agenda anzeigen, um den Zeitraum für die Sitzung zu wechseln</string>
<string name="agenda_range_day">Heute</string> <string name="agenda_range_day">Heute</string>
<string name="agenda_range_this_week">Diese Woche</string> <string name="agenda_range_this_week">Diese Woche</string>
<string name="agenda_range_this_month">Dieser Monat</string> <string name="agenda_range_this_month">Dieser Monat</string>

View File

@@ -278,10 +278,8 @@
<string name="settings_agenda_range_hint">How far ahead the Agenda screen lists events.</string> <string name="settings_agenda_range_hint">How far ahead the Agenda screen lists events.</string>
<string name="settings_agenda_widget_range">Agenda widget range</string> <string name="settings_agenda_widget_range">Agenda widget range</string>
<string name="settings_agenda_widget_range_hint">How far ahead the agenda home-screen widget lists events.</string> <string name="settings_agenda_widget_range_hint">How far ahead the agenda home-screen widget lists events.</string>
<string name="settings_agenda_range_title">Range title</string> <string name="settings_agenda_range_bar">Range bar</string>
<string name="settings_agenda_range_title_hint">Show a header naming the dates the agenda is showing</string> <string name="settings_agenda_range_bar_hint">Show a bar at the top of the agenda naming the dates shown, with a button to switch the range for the session</string>
<string name="settings_agenda_range_button">Range button</string>
<string name="settings_agenda_range_button_hint">Show a button in the agenda to switch the range for the session</string>
<string name="agenda_range_day">Today</string> <string name="agenda_range_day">Today</string>
<string name="agenda_range_this_week">This week</string> <string name="agenda_range_this_week">This week</string>
<string name="agenda_range_this_month">This month</string> <string name="agenda_range_this_month">This month</string>