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() }
}
/** Whether the agenda shows its range-header banner (v2.11). Default ON. */
val agendaShowRangeBanner: Flow<Boolean> = store.data.map { prefs ->
prefs[AGENDA_SHOW_RANGE_BANNER_KEY] ?: true
/**
* Whether the agenda shows its top range bar — the "showing …" header and
* 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) {
store.edit { it[AGENDA_SHOW_RANGE_BANNER_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 }
suspend fun setAgendaShowRangeBar(enabled: Boolean) {
store.edit { it[AGENDA_SHOW_RANGE_BAR_KEY] = enabled }
}
/**
@@ -346,8 +340,7 @@ class SettingsPrefs @Inject constructor(
internal val WEEK_START_KEY = stringPreferencesKey("week_start")
internal val AGENDA_SCREEN_RANGE_KEY = stringPreferencesKey("agenda_screen_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_PILL_KEY = booleanPreferencesKey("agenda_show_range_pill")
internal val AGENDA_SHOW_RANGE_BAR_KEY = booleanPreferencesKey("agenda_show_range_bar")
internal val TIME_FORMAT_KEY = stringPreferencesKey("time_format")
internal val SHOW_HOUR_LINES_KEY = booleanPreferencesKey("show_hour_lines")
internal val DEFAULT_VIEW_KEY = stringPreferencesKey("default_view")

View File

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

View File

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

View File

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

View File

@@ -518,28 +518,16 @@ private fun AppearanceScreen(
onClick = { showAgendaWidgetRange = true },
)
GroupedRow(
title = stringResource(R.string.settings_agenda_range_title),
summary = stringResource(R.string.settings_agenda_range_title_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),
title = stringResource(R.string.settings_agenda_range_bar),
summary = stringResource(R.string.settings_agenda_range_bar_hint),
position = Position.Bottom,
trailing = {
Switch(
checked = state.agendaShowRangePill,
onCheckedChange = viewModel::setAgendaShowRangePill,
checked = state.agendaShowRangeBar,
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,
/** How far ahead the agenda widget shows events (v2.11). */
val agendaWidgetRange: AgendaRange = AgendaRange.Month,
/** Whether the agenda shows its range-header banner (v2.11). */
val agendaShowRangeBanner: Boolean = true,
/** Whether the agenda shows the bottom-left range pill (v2.11). */
val agendaShowRangePill: Boolean = true,
/** Whether the agenda shows its top range bar — header + switcher (v2.11). */
val agendaShowRangeBar: Boolean = true,
/** The calendar view the app opens on, and the home of the view back stack (M1). */
val defaultView: CalendarView = CalendarView.Week,
/** 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 ->
ViewSettings(view, screenRange, widgetRange, timeFormat, showHourLines)
},
combine(
prefs.agendaShowRangeBanner,
prefs.agendaShowRangePill,
) { banner, pill -> banner to pill },
) { base, defaults, overrides, views, agendaToggles ->
prefs.agendaShowRangeBar,
) { base, defaults, overrides, views, showRangeBar ->
base.copy(
defaultView = views.defaultView,
agendaScreenRange = views.agendaScreenRange,
agendaWidgetRange = views.agendaWidgetRange,
timeFormat = views.timeFormat,
showHourLines = views.showHourLines,
agendaShowRangeBanner = agendaToggles.first,
agendaShowRangePill = agendaToggles.second,
agendaShowRangeBar = showRangeBar,
allowColorOnUnsupportedCalendars = defaults.allowColor,
defaultReminderMinutes = defaults.defaultReminder,
defaultAllDayReminderMinutes = defaults.allDayReminder,
@@ -154,12 +150,8 @@ class SettingsViewModel @Inject constructor(
viewModelScope.launch { prefs.setAgendaWidgetRange(range) }
}
fun setAgendaShowRangeBanner(enabled: Boolean) {
viewModelScope.launch { prefs.setAgendaShowRangeBanner(enabled) }
}
fun setAgendaShowRangePill(enabled: Boolean) {
viewModelScope.launch { prefs.setAgendaShowRangePill(enabled) }
fun setAgendaShowRangeBar(enabled: Boolean) {
viewModelScope.launch { prefs.setAgendaShowRangeBar(enabled) }
}
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_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_range_title">Zeitraum-Titel</string>
<string name="settings_agenda_range_title_hint">Eine Überschrift anzeigen, die den dargestellten Zeitraum benennt</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="settings_agenda_range_bar">Zeitraum-Leiste</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="agenda_range_day">Heute</string>
<string name="agenda_range_this_week">Diese Woche</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_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_range_title">Range title</string>
<string name="settings_agenda_range_title_hint">Show a header naming the dates the agenda is showing</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="settings_agenda_range_bar">Range bar</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="agenda_range_day">Today</string>
<string name="agenda_range_this_week">This week</string>
<string name="agenda_range_this_month">This month</string>