feat: dim past events when enabled (month bars, week/day grid, agenda)

Past events (endDate before now) are drawn at reduced opacity across the month
bars, the week/day time grid (timed + all-day) and the agenda list when the
'dim past events' setting is on.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Guido Schmit
2026-05-31 15:26:05 +02:00
parent bc93964e05
commit 9467fe7bb6
3 changed files with 26 additions and 6 deletions

View File

@@ -21,6 +21,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
@@ -38,6 +39,8 @@ fun AgendaView(
onEventClick: (CalEvent) -> Unit, onEventClick: (CalEvent) -> Unit,
) { ) {
val lang = LocalLang.current val lang = LocalLang.current
val dimPast = com.scarriffle.calendarr.ui.LocalAppSettings.current.dimPastEvents
val now = java.time.Instant.now()
val today = LocalDate.now() val today = LocalDate.now()
val days = (0 until 90).map { today.plusDays(it.toLong()) } val days = (0 until 90).map { today.plusDays(it.toLong()) }
.map { it to vm.eventsOn(it, state.events) } .map { it to vm.eventsOn(it, state.events) }
@@ -72,7 +75,7 @@ fun AgendaView(
) )
} }
items(events, key = { "${date}-${it.id}" }) { ev -> items(events, key = { "${date}-${it.id}" }) { ev ->
AgendaRow(ev, lang, onClick = { onEventClick(ev) }) AgendaRow(ev, lang, dimmed = dimPast && ev.endDate.isBefore(now), onClick = { onEventClick(ev) })
} }
} }
item { Spacer(Modifier.height(80.dp)) } item { Spacer(Modifier.height(80.dp)) }
@@ -80,11 +83,12 @@ fun AgendaView(
} }
@Composable @Composable
private fun AgendaRow(event: CalEvent, lang: String, onClick: () -> Unit) { private fun AgendaRow(event: CalEvent, lang: String, dimmed: Boolean, onClick: () -> Unit) {
Row( Row(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 4.dp) .padding(vertical = 4.dp)
.alpha(if (dimmed) 0.45f else 1f)
.clip(RoundedCornerShape(10.dp)) .clip(RoundedCornerShape(10.dp))
.background(MaterialTheme.colorScheme.surface) .background(MaterialTheme.colorScheme.surface)
.clickable(onClick = onClick) .clickable(onClick = onClick)

View File

@@ -28,6 +28,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
@@ -142,6 +143,8 @@ fun MonthView(
} }
val eventsByWeek = remember(state.events, mondayFirst) { buildEventsByWeek(state.events, mondayFirst) } val eventsByWeek = remember(state.events, mondayFirst) { buildEventsByWeek(state.events, mondayFirst) }
val dimPast = settings.dimPastEvents
val now = java.time.Instant.now()
Column(Modifier.fillMaxSize()) { Column(Modifier.fillMaxSize()) {
Row(Modifier.fillMaxWidth().padding(vertical = 3.dp)) { Row(Modifier.fillMaxWidth().padding(vertical = 3.dp)) {
@@ -167,6 +170,8 @@ fun MonthView(
today = today, today = today,
weekEvents = eventsByWeek[weekStart] ?: emptyList(), weekEvents = eventsByWeek[weekStart] ?: emptyList(),
cellW = cellW, cellW = cellW,
dimPast = dimPast,
now = now,
lang = lang, lang = lang,
dividerColor = dividerColor, dividerColor = dividerColor,
gridColor = gridColor, gridColor = gridColor,
@@ -188,6 +193,8 @@ private fun WeekRow(
today: LocalDate, today: LocalDate,
weekEvents: List<CalEvent>, weekEvents: List<CalEvent>,
cellW: Dp, cellW: Dp,
dimPast: Boolean,
now: java.time.Instant,
lang: String, lang: String,
dividerColor: Color, dividerColor: Color,
gridColor: Color, gridColor: Color,
@@ -235,7 +242,8 @@ private fun WeekRow(
} }
packed.bars.forEach { bar -> packed.bars.forEach { bar ->
EventBar(bar = bar, cellW = cellW, onClick = { onEventClick(bar.event) }) val past = dimPast && bar.event.endDate.isBefore(now)
EventBar(bar = bar, cellW = cellW, dimmed = past, onClick = { onEventClick(bar.event) })
} }
if (boundaryCol != null) { if (boundaryCol != null) {
@@ -251,7 +259,7 @@ private fun WeekRow(
} }
@Composable @Composable
private fun EventBar(bar: PlacedBar, cellW: Dp, onClick: () -> Unit) { private fun EventBar(bar: PlacedBar, cellW: Dp, dimmed: Boolean, onClick: () -> Unit) {
Box( Box(
Modifier Modifier
.offset( .offset(
@@ -260,6 +268,7 @@ private fun EventBar(bar: PlacedBar, cellW: Dp, onClick: () -> Unit) {
) )
.width(cellW * bar.span - 2.dp) .width(cellW * bar.span - 2.dp)
.height(LANE_H) .height(LANE_H)
.alpha(if (dimmed) 0.45f else 1f)
.clip(RoundedCornerShape(3.dp)) .clip(RoundedCornerShape(3.dp))
.background(bar.color) .background(bar.color)
.clickable(onClick = onClick) .clickable(onClick = onClick)

View File

@@ -20,6 +20,7 @@ import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.layout import androidx.compose.ui.layout.layout
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
@@ -45,6 +46,8 @@ fun TimeGridView(
onEventClick: (CalEvent) -> Unit, onEventClick: (CalEvent) -> Unit,
) { ) {
val hourHeight = LocalAppSettings.current.hourHeight.coerceIn(28, 100).dp val hourHeight = LocalAppSettings.current.hourHeight.coerceIn(28, 100).dp
val dimPast = LocalAppSettings.current.dimPastEvents
val now = java.time.Instant.now()
val lang = LocalLang.current val lang = LocalLang.current
val today = LocalDate.now() val today = LocalDate.now()
@@ -76,7 +79,7 @@ fun TimeGridView(
} }
allDay.forEach { (_, evs) -> allDay.forEach { (_, evs) ->
Column(Modifier.weight(1f).padding(horizontal = 1.dp)) { Column(Modifier.weight(1f).padding(horizontal = 1.dp)) {
evs.forEach { ev -> AllDayChip(ev, onClick = { onEventClick(ev) }) } evs.forEach { ev -> AllDayChip(ev, dimmed = dimPast && ev.endDate.isBefore(now), onClick = { onEventClick(ev) }) }
} }
} }
} }
@@ -117,6 +120,7 @@ fun TimeGridView(
index = index, index = index,
dayCount = days.size, dayCount = days.size,
hourHeight = hourHeight, hourHeight = hourHeight,
dimmed = dimPast && ev.endDate.isBefore(now),
onClick = { onEventClick(ev) }, onClick = { onEventClick(ev) },
) )
} }
@@ -133,6 +137,7 @@ private fun TimedEvent(
index: Int, index: Int,
dayCount: Int, dayCount: Int,
hourHeight: androidx.compose.ui.unit.Dp, hourHeight: androidx.compose.ui.unit.Dp,
dimmed: Boolean,
onClick: () -> Unit, onClick: () -> Unit,
) { ) {
val startMin = if (localDate(event.startDate).isBefore(day)) 0 else minutesOfDay(event.startDate) val startMin = if (localDate(event.startDate).isBefore(day)) 0 else minutesOfDay(event.startDate)
@@ -149,6 +154,7 @@ private fun TimedEvent(
.columnSlot(index, dayCount) .columnSlot(index, dayCount)
.height(height) .height(height)
.padding(horizontal = 1.dp, vertical = 0.5.dp) .padding(horizontal = 1.dp, vertical = 0.5.dp)
.alpha(if (dimmed) 0.45f else 1f)
.clip(RoundedCornerShape(4.dp)) .clip(RoundedCornerShape(4.dp))
.background(color) .background(color)
.clickable(onClick = onClick) .clickable(onClick = onClick)
@@ -188,12 +194,13 @@ private fun Modifier.columnSlot(index: Int, dayCount: Int): Modifier = layout {
} }
@Composable @Composable
private fun AllDayChip(event: CalEvent, onClick: () -> Unit) { private fun AllDayChip(event: CalEvent, dimmed: Boolean, onClick: () -> Unit) {
val color = colorFromHex(event.effectiveColor) val color = colorFromHex(event.effectiveColor)
Box( Box(
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = 1.dp) .padding(vertical = 1.dp)
.alpha(if (dimmed) 0.45f else 1f)
.clip(RoundedCornerShape(3.dp)) .clip(RoundedCornerShape(3.dp))
.background(color) .background(color)
.clickable(onClick = onClick) .clickable(onClick = onClick)