Merge pull request 'Widgets: readable dimmed events, pinned theme matches system (#475)' (#500) from fix/475-widget-feedback into release/2.24.1
Beta — Codeberg pre-release / detect (push) Successful in 5s
Beta — Codeberg pre-release / beta (push) Skipped

This commit is contained in:
Jean-Luc Makiola committed 2026-11-09 21:06:55 +01:00
commit a92dd013bc
2 files changed
+33 -20

No files matched your search

@@ -2,6 +2,7 @@ package de.jeanlucmakiola.calendula.widget
import androidx.compose.runtime.Composable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.dp
@@ -25,20 +26,33 @@ import de.jeanlucmakiola.calendula.ui.common.CalendarView
import de.jeanlucmakiola.calendula.ui.common.SECONDARY_INK_ALPHA
import de.jeanlucmakiola.calendula.ui.common.eventFill
import de.jeanlucmakiola.calendula.ui.common.eventInk
import de.jeanlucmakiola.calendula.ui.theme.CalendulaDarkFallback
import de.jeanlucmakiola.calendula.widget.agenda.metricsFor
import de.jeanlucmakiola.floret.components.Position
import de.jeanlucmakiola.floret.glance.WidgetGroupedRow
import de.jeanlucmakiola.floret.glance.themedColor
/** A past event's fill when dimmed: fainter than the app's whole-row dim, so its text can stay readable (#90). */
internal const val WidgetDimFillAlpha = 0.3f
/** How much of a past event's tone stays in its dimmed fill (#90). */
private const val WidgetDimFillAlpha = 0.3f
/** A dimmed event's ink, held above its fill. */
private const val WidgetDimInkAlpha = 0.65f
/** Ink for an event on [fill], picked against the opaque tone and faded when the fill is dimmed. */
internal fun widgetEventInk(fill: Color, alpha: Float): Color =
eventInk(fill.copy(alpha = 1f), if (fill.alpha < 1f) alpha * WidgetDimInkAlpha else alpha)
/**
* An event's fill in the light or [dark] theme. A dimmed one is its tone faded
* into that theme's surface, kept opaque: a translucent tint lands on the row
* shape's white, not on the widget, and its ink would be picked for the wrong tone (#475).
*/
internal fun widgetEventFill(rawArgb: Int, dark: Boolean, soften: Boolean, dimmed: Boolean): Color {
val tone = eventFill(rawArgb, dark, soften)
if (!dimmed) return tone
val surface = if (dark) CalendulaDarkFallback.surface else Color.White
return tone.copy(alpha = WidgetDimFillAlpha).compositeOver(surface)
}
/** Ink for an event on [fill], faded when the row is [dimmed]. */
internal fun widgetEventInk(fill: Color, alpha: Float, dimmed: Boolean): Color =
eventInk(fill, if (dimmed) alpha * WidgetDimInkAlpha else alpha)
/** Text and row sizes of a compact event list, from a widget's [WidgetSize]. */
internal data class EventRowMetrics(val title: TextUnit, val time: TextUnit, val rowHeight: Dp, val message: TextUnit)
@@ -71,9 +85,8 @@ internal fun WidgetEventRow(
quiet: Boolean = false,
) {
val context = LocalContext.current
fun tone(dark: Boolean): Color = eventFill(event.color, dark, soften).let { if (dimmed) it.copy(alpha = WidgetDimFillAlpha) else it }
val day = tone(dark = false)
val night = tone(dark = true)
val day = widgetEventFill(event.color, dark = false, soften, dimmed)
val night = widgetEventFill(event.color, dark = true, soften, dimmed)
val card = widgetCardColor()
WidgetGroupedRow(position = position, color = if (quiet) card else themedColor(day = day, night = night)) {
Column(
@@ -91,12 +104,12 @@ internal fun WidgetEventRow(
val titleInk = if (quiet) {
GlanceTheme.colors.onSurface
} else {
themedColor(day = widgetEventInk(day, 1f), night = widgetEventInk(night, 1f))
themedColor(day = widgetEventInk(day, 1f, dimmed), night = widgetEventInk(night, 1f, dimmed))
}
val timeInk = if (quiet) {
GlanceTheme.colors.onSurfaceVariant
} else {
themedColor(day = widgetEventInk(day, SECONDARY_INK_ALPHA), night = widgetEventInk(night, SECONDARY_INK_ALPHA))
themedColor(day = widgetEventInk(day, SECONDARY_INK_ALPHA, dimmed), night = widgetEventInk(night, SECONDARY_INK_ALPHA, dimmed))
}
Text(
text = event.title.ifBlank { context.getString(R.string.event_untitled) },
@@ -56,7 +56,7 @@ import de.jeanlucmakiola.calendula.ui.agenda.anchorTodayIfMissing
import de.jeanlucmakiola.calendula.ui.common.CalendarView
import de.jeanlucmakiola.calendula.ui.common.formatCalendarTitle
import de.jeanlucmakiola.floret.locale.localizedDateFormatter
import de.jeanlucmakiola.calendula.ui.common.eventFill
import de.jeanlucmakiola.calendula.widget.widgetEventFill
import de.jeanlucmakiola.calendula.ui.common.eventAccent
import de.jeanlucmakiola.calendula.ui.common.EventDimAlpha
import de.jeanlucmakiola.calendula.widget.AgendaWidgetStyle
@@ -65,7 +65,6 @@ import de.jeanlucmakiola.floret.glance.LocalWidgetSeeThrough
import androidx.compose.runtime.CompositionLocalProvider
import de.jeanlucmakiola.floret.glance.WidgetBackground
import de.jeanlucmakiola.floret.glance.withAlpha
import de.jeanlucmakiola.calendula.widget.WidgetDimFillAlpha
import de.jeanlucmakiola.calendula.widget.widgetEventInk
import de.jeanlucmakiola.calendula.ui.common.SECONDARY_INK_ALPHA
import de.jeanlucmakiola.calendula.widget.AgendaWidgetData
@@ -592,7 +591,7 @@ private fun PlaceholderRow(date: LocalDate, metrics: AgendaMetrics) {
}
/** An event row's light and dark fill: its calendar's container tone, faded when the row is dimmed. */
private data class EventFill(val day: Color, val night: Color)
private data class EventFill(val day: Color, val night: Color, val dimmed: Boolean)
/** Whether this row is drawn faded as a finished event. */
private fun AgendaRow.Event.dimmed(data: AgendaWidgetData.Ready): Boolean =
@@ -600,10 +599,11 @@ private fun AgendaRow.Event.dimmed(data: AgendaWidgetData.Ready): Boolean =
private fun AgendaRow.Event.fill(data: AgendaWidgetData.Ready): EventFill {
val dimmed = dimmed(data)
fun tone(dark: Boolean) = eventFill(event.color, dark, data.soften).let {
if (dimmed) it.copy(alpha = WidgetDimFillAlpha) else it
}
return EventFill(day = tone(dark = false), night = tone(dark = true))
return EventFill(
day = widgetEventFill(event.color, dark = false, data.soften, dimmed),
night = widgetEventFill(event.color, dark = true, data.soften, dimmed),
dimmed = dimmed,
)
}
@Composable
@@ -616,10 +616,10 @@ private fun EventRow(
) {
val context = androidx.glance.LocalContext.current
val title = event.title.ifBlank { context.getString(R.string.event_untitled) }
val titleInk = themedColor(day = widgetEventInk(fill.day, 1f), night = widgetEventInk(fill.night, 1f))
val titleInk = themedColor(day = widgetEventInk(fill.day, 1f, fill.dimmed), night = widgetEventInk(fill.night, 1f, fill.dimmed))
val timeInk = themedColor(
day = widgetEventInk(fill.day, SECONDARY_INK_ALPHA),
night = widgetEventInk(fill.night, SECONDARY_INK_ALPHA),
day = widgetEventInk(fill.day, SECONDARY_INK_ALPHA, fill.dimmed),
night = widgetEventInk(fill.night, SECONDARY_INK_ALPHA, fill.dimmed),
)
Column(
modifier = GlanceModifier