Share one body for the editor's picker cards

This commit is contained in:
makiolaj committed 2026-10-16 14:07:39 +02:00
1 parent 3ed12f1fee
commit 7a43ee0595
1 file changed
+82 -116
@@ -658,6 +658,45 @@ private fun SaveConflictDialog(
private enum class PickerTarget { StartDate, StartTime, EndDate, EndTime }
/** A picker card's value over its label, with the drop-down arrow when it opens a picker. */
@Composable
private fun PickerCardBody(
title: String,
subtitle: String,
showArrow: Boolean = true,
extra: @Composable ColumnScope.() -> Unit = {},
) = PickerCardBody(AnnotatedString(title), subtitle, showArrow, extra)
@Composable
private fun PickerCardBody(
title: AnnotatedString,
subtitle: String,
showArrow: Boolean = true,
extra: @Composable ColumnScope.() -> Unit = {},
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Column(modifier = Modifier.weight(1f)) {
Text(text = title, style = MaterialTheme.typography.titleMedium)
Text(
text = subtitle,
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
extra()
}
if (showArrow) {
Icon(
imageVector = Icons.Default.ArrowDropDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}
/**
* Wrapper for an optional form section: fields added via "more fields"
* spring open with the expressive spatial spec instead of popping in.
@@ -949,44 +988,26 @@ private fun EventEditContent(
iconContentDescription = null,
onClick = { showTimezonePicker = true },
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
// Resolved at the event's own start, not at "now": the
// abbreviation and offset shown ("CEST · GMT+02:00") must be
// the ones that apply when the event actually happens.
val pinned = remember(form.timezone, form.start, locale) {
form.timezone
?.let { id -> runCatching { id to TimeZone.of(id) }.getOrNull() }
?.let { (id, zone) ->
timeZoneOptionOf(
id,
locale,
at = form.startInstant(zone).toJavaInstant(),
regionOf = ::icuTimeZoneRegion,
)
}
}
Column(modifier = Modifier.weight(1f)) {
Text(
text = pinned?.label
?: stringResource(R.string.event_edit_timezone_device),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = pinned?.let { zoneDescriptor(it) }
?: stringResource(R.string.event_edit_timezone_device_summary),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Icon(
imageVector = Icons.Default.ArrowDropDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
// Resolved at the event's own start, not at "now": the
// abbreviation and offset shown ("CEST · GMT+02:00") must be
// the ones that apply when the event actually happens.
val pinned = remember(form.timezone, form.start, locale) {
form.timezone
?.let { id -> runCatching { id to TimeZone.of(id) }.getOrNull() }
?.let { (id, zone) ->
timeZoneOptionOf(
id,
locale,
at = form.startInstant(zone).toJavaInstant(),
regionOf = ::icuTimeZoneRegion,
)
}
}
PickerCardBody(
title = pinned?.label ?: stringResource(R.string.event_edit_timezone_device),
subtitle = pinned?.let { zoneDescriptor(it) }
?: stringResource(R.string.event_edit_timezone_device_summary),
)
}
}
@@ -1107,28 +1128,11 @@ private fun EventEditContent(
iconContentDescription = null,
onClick = if (locked) null else ({ showRecurrencePicker = true }),
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = form.rrule?.let { recurrenceText(it, locale) }
?: AnnotatedString(stringResource(R.string.event_edit_recurrence_none)),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = stringResource(R.string.event_detail_recurrence),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Icon(
imageVector = Icons.Default.ArrowDropDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
PickerCardBody(
title = form.rrule?.let { recurrenceText(it, locale) }
?: AnnotatedString(stringResource(R.string.event_edit_recurrence_none)),
subtitle = stringResource(R.string.event_detail_recurrence),
)
if (EventFormProblem.RecurrenceEndsBeforeStart in state.problems) {
Spacer(Modifier.height(2.dp))
Text(
@@ -1175,27 +1179,10 @@ private fun EventEditContent(
iconContentDescription = null,
onClick = { showVisibilityPicker = true },
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
) {
Column(modifier = Modifier.weight(1f)) {
Text(
text = stringResource(accessLevelLabel(form.accessLevel)),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = stringResource(R.string.event_edit_visibility),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
Icon(
imageVector = Icons.Default.ArrowDropDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
PickerCardBody(
title = stringResource(accessLevelLabel(form.accessLevel)),
subtitle = stringResource(R.string.event_edit_visibility),
)
}
}
@@ -1214,47 +1201,26 @@ private fun EventEditContent(
},
onClick = { showColorPicker = true }.takeIf { colorSupported },
) {
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier.fillMaxWidth(),
PickerCardBody(
title = stringResource(
when {
!colorSupported -> R.string.event_edit_color_unsupported
form.color != null -> R.string.event_edit_color_custom
else -> R.string.event_edit_color_default
},
),
subtitle = stringResource(
if (colorSupported) R.string.event_edit_color else R.string.event_edit_color_unsupported_hint,
),
showArrow = colorSupported,
) {
Column(modifier = Modifier.weight(1f)) {
if (colorSyncRisk) {
Spacer(Modifier.height(2.dp))
Text(
text = stringResource(
when {
!colorSupported -> R.string.event_edit_color_unsupported
form.color != null -> R.string.event_edit_color_custom
else -> R.string.event_edit_color_default
},
),
style = MaterialTheme.typography.titleMedium,
)
Text(
text = stringResource(
if (colorSupported) {
R.string.event_edit_color
} else {
R.string.event_edit_color_unsupported_hint
},
),
text = stringResource(R.string.event_edit_color_sync_warning),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
if (colorSyncRisk) {
Spacer(Modifier.height(2.dp))
Text(
text = stringResource(R.string.event_edit_color_sync_warning),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
if (colorSupported) {
Icon(
imageVector = Icons.Default.ArrowDropDown,
contentDescription = null,
tint = MaterialTheme.colorScheme.onSurfaceVariant,
)
}
}
}