fix(edit): recurrence picker review fixes + picker unification (#42) #89

Merged
makiolaj merged 6 commits from feat/recurrence-exdate into release/v2.16.0 2026-07-20 13:29:16 +00:00
Showing only changes of commit ccd433fee1 - Show all commits

View File

@@ -1382,8 +1382,43 @@ private fun RecurrencePickerDialog(
) )
} else { } else {
Column( Column(
verticalArrangement = Arrangement.spacedBy(8.dp), modifier = Modifier.fillMaxWidth(),
modifier = Modifier.padding(horizontal = 24.dp), verticalArrangement = Arrangement.spacedBy(16.dp),
) {
// A live, human-readable read-out of the rule being built, so the
// effect of the controls below is never a guess.
Text(
text = recurrenceText(
SimpleRecurrence(
freq = freq,
interval = interval ?: 1,
end = customEnd ?: RecurrenceEnd.Never,
byDays = if (freq == RecurrenceFreq.Weekly) {
daysMask.toDaySet()
} else {
emptySet()
},
).toRRule(),
locale,
),
style = MaterialTheme.typography.titleMedium,
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
)
// How often: an interval amount plus a frequency segmented row —
// all four units on show, no unit hidden behind a dropdown.
Surface(
color = MaterialTheme.colorScheme.surfaceContainerHigh,
shape = groupedShape(Position.Alone),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
) {
Column(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(16.dp),
) { ) {
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
Text( Text(
@@ -1396,31 +1431,52 @@ private fun RecurrencePickerDialog(
onValueChange = { intervalText = it }, onValueChange = { intervalText = it },
placeholder = "1", placeholder = "1",
) )
Spacer(Modifier.width(12.dp)) }
DialogUnitDropdown( SingleChoiceSegmentedButtonRow(modifier = Modifier.fillMaxWidth()) {
label = stringResource(recurrenceUnitLabel(freq)), RecurrenceFreq.entries.forEachIndexed { index, entry ->
entries = RecurrenceFreq.entries.map { SegmentedButton(
stringResource(recurrenceUnitLabel(it)) selected = freq == entry,
}, onClick = { freq = entry },
onPick = { freq = RecurrenceFreq.entries[it] }, shape = SegmentedButtonDefaults.itemShape(
index, RecurrenceFreq.entries.size,
),
label = { Text(stringResource(recurrenceUnitLabel(entry))) },
) )
} }
if (freq == RecurrenceFreq.Weekly) { }
}
}
// Weekday picks — only meaningful on a weekly rule.
AnimatedVisibility(visible = freq == RecurrenceFreq.Weekly) {
Surface(
color = MaterialTheme.colorScheme.surfaceContainerHigh,
shape = groupedShape(Position.Alone),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
) {
WeekdayToggleRow( WeekdayToggleRow(
selected = daysMask.toDaySet(), selected = daysMask.toDaySet(),
onToggle = { day -> daysMask = daysMask xor day.toMaskBit() }, onToggle = { day -> daysMask = daysMask xor day.toMaskBit() },
locale = locale, locale = locale,
modifier = Modifier.padding(16.dp),
) )
} }
}
// Ends: a connected never / on-a-date / after-N group, the count
// field folding into the bottom of the run when chosen.
Column {
Text( Text(
text = stringResource(R.string.event_edit_recurrence_ends), text = stringResource(R.string.event_edit_recurrence_ends),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
modifier = Modifier.padding(start = 16.dp, bottom = 8.dp),
) )
}
GroupedRow( GroupedRow(
title = stringResource(R.string.event_edit_recurrence_end_never), title = stringResource(R.string.event_edit_recurrence_end_never),
position = positionOf(0, 3), position = Position.Top,
selected = endMode == RecurrenceEndMode.Never, selected = endMode == RecurrenceEndMode.Never,
onClick = { endMode = RecurrenceEndMode.Never }, onClick = { endMode = RecurrenceEndMode.Never },
) )
@@ -1432,7 +1488,7 @@ private fun RecurrencePickerDialog(
.withLocale(locale).format(it.toJavaLocalDate()) .withLocale(locale).format(it.toJavaLocalDate())
} }
}, },
position = positionOf(1, 3), position = Position.Middle,
selected = endMode == RecurrenceEndMode.Until, selected = endMode == RecurrenceEndMode.Until,
onClick = { onClick = {
endMode = RecurrenceEndMode.Until endMode = RecurrenceEndMode.Until
@@ -1441,14 +1497,25 @@ private fun RecurrencePickerDialog(
) )
GroupedRow( GroupedRow(
title = stringResource(R.string.event_edit_recurrence_end_count), title = stringResource(R.string.event_edit_recurrence_end_count),
position = positionOf(2, 3), position = if (endMode == RecurrenceEndMode.Count) {
Position.Middle
} else {
Position.Bottom
},
selected = endMode == RecurrenceEndMode.Count, selected = endMode == RecurrenceEndMode.Count,
onClick = { endMode = RecurrenceEndMode.Count }, onClick = { endMode = RecurrenceEndMode.Count },
) )
if (endMode == RecurrenceEndMode.Count) { if (endMode == RecurrenceEndMode.Count) {
Surface(
color = MaterialTheme.colorScheme.surfaceContainerHigh,
shape = groupedShape(Position.Bottom),
modifier = Modifier
.fillMaxWidth()
.padding(horizontal = 16.dp),
) {
Row( Row(
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 4.dp), modifier = Modifier.padding(16.dp),
) { ) {
DialogAmountField( DialogAmountField(
value = countText, value = countText,
@@ -1464,6 +1531,9 @@ private fun RecurrencePickerDialog(
} }
} }
} }
}
}
}
if (showUntilPicker) { if (showUntilPicker) {
CalendarDatePickerDialog( CalendarDatePickerDialog(
@@ -1489,6 +1559,7 @@ private fun WeekdayToggleRow(
selected: Set<DayOfWeek>, selected: Set<DayOfWeek>,
onToggle: (DayOfWeek) -> Unit, onToggle: (DayOfWeek) -> Unit,
locale: Locale, locale: Locale,
modifier: Modifier = Modifier,
) { ) {
val days = remember(locale) { val days = remember(locale) {
val first = WeekFields.of(locale).firstDayOfWeek.toKotlinDayOfWeek() val first = WeekFields.of(locale).firstDayOfWeek.toKotlinDayOfWeek()
@@ -1496,7 +1567,7 @@ private fun WeekdayToggleRow(
} }
Row( Row(
horizontalArrangement = Arrangement.SpaceBetween, horizontalArrangement = Arrangement.SpaceBetween,
modifier = Modifier.fillMaxWidth(), modifier = modifier.fillMaxWidth(),
) { ) {
days.forEach { day -> days.forEach { day ->
val isSelected = day in selected val isSelected = day in selected