feat: week-of-year numbers in Month view (#25) #64

Merged
makiolaj merged 3 commits from feat/month-week-numbers into release/v2.14.0 2026-07-06 20:26:14 +00:00
3 changed files with 38 additions and 48 deletions
Showing only changes of commit 1f050c2be9 - Show all commits

View File

@@ -1,38 +0,0 @@
package de.jeanlucmakiola.calendula.ui.common
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.jeanlucmakiola.calendula.R
/**
* Calendar-week badge — a filled tonal chip with a bold number, deliberately set
* apart from the surrounding day numbers. Shared by the Week and Month views so
* the week-of-year indicator reads identically wherever it appears.
*/
@Composable
fun WeekNumberBadge(weekNumber: Int, modifier: Modifier = Modifier) {
val label = stringResource(R.string.week_number_label)
Surface(
shape = RoundedCornerShape(8.dp),
color = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
modifier = modifier.semantics { contentDescription = "$label $weekNumber" },
) {
Text(
text = weekNumber.toString(),
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp),
)
}
}

View File

@@ -73,7 +73,6 @@ import de.jeanlucmakiola.calendula.ui.common.EventDimAlpha
import de.jeanlucmakiola.calendula.ui.common.LocalDimCutoff
import de.jeanlucmakiola.calendula.ui.common.rememberCurrentMinute
import de.jeanlucmakiola.calendula.ui.common.ViewSwitcherPill
import de.jeanlucmakiola.calendula.ui.common.WeekNumberBadge
import de.jeanlucmakiola.calendula.ui.common.calendarSlideTransition
import de.jeanlucmakiola.calendula.ui.common.rememberCalendarFadeSpec
import de.jeanlucmakiola.calendula.ui.common.rememberReduceMotion
@@ -361,8 +360,8 @@ private fun WeekdayHeader(weekStart: DayOfWeek, showWeekNumbers: Boolean) {
private val EVENT_ROW_HEIGHT = 20.dp
private val DAY_NUMBER_HEIGHT = 22.dp
/** Width of the optional left gutter holding the calendar-week badge (#25); wide
* enough to seat the shared [WeekNumberBadge] with a little breathing room. */
/** Width of the optional left calendar-week gutter (#25); narrow, since it only
* seats a one- or two-digit week number in a full-height tonal pill. */
private val WEEK_NUMBER_GUTTER = 40.dp
private val DAY_NUMBER_GAP = 4.dp
private val CELL_TOP_PADDING = 6.dp
@@ -564,10 +563,11 @@ private fun MonthWeekRow(
}
/**
* Left-gutter calendar-week indicator (#25), centred vertically in the row. Uses
* the shared [WeekNumberBadge] so it's identical to the Week view's, and computes
* the ISO week-of-week-based-year on the row's first day — the same basis — so the
* two views always agree.
* Left-gutter calendar-week cell (#25): a full-height tonal pill mirroring the
* day cells' geometry, set apart by the secondaryContainer tint (matching the
* Week view's badge), with the ISO week number centred like a day number. The
* week is computed on the row's first day — the same basis as the Week view — so
* the two agree.
*/
@Composable
private fun WeekNumberGutter(weekStart: LocalDate, modifier: Modifier = Modifier) {
@@ -575,11 +575,20 @@ private fun WeekNumberGutter(weekStart: LocalDate, modifier: Modifier = Modifier
java.time.LocalDate.of(weekStart.year, weekStart.month.ordinal + 1, weekStart.day)
.get(java.time.temporal.IsoFields.WEEK_OF_WEEK_BASED_YEAR)
}
val label = stringResource(R.string.week_number_label)
Box(
modifier = modifier,
modifier = modifier
.padding(horizontal = CELL_GAP, vertical = 1.dp)
.background(MaterialTheme.colorScheme.secondaryContainer, CELL_SHAPE)
.semantics { contentDescription = "$label $weekNumber" },
contentAlignment = Alignment.Center,
) {
WeekNumberBadge(weekNumber = weekNumber)
Text(
text = weekNumber.toString(),
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold,
color = MaterialTheme.colorScheme.onSecondaryContainer,
)
}
}

View File

@@ -87,7 +87,6 @@ import de.jeanlucmakiola.calendula.ui.common.LocalDimCutoff
import de.jeanlucmakiola.calendula.ui.common.NowLine
import de.jeanlucmakiola.calendula.ui.common.rememberCurrentMinute
import de.jeanlucmakiola.calendula.ui.common.ViewSwitcherPill
import de.jeanlucmakiola.calendula.ui.common.WeekNumberBadge
import de.jeanlucmakiola.calendula.ui.common.calendarSlideTransition
import de.jeanlucmakiola.calendula.ui.common.rememberCalendarFadeSpec
import de.jeanlucmakiola.calendula.ui.common.rememberReduceMotion
@@ -508,6 +507,26 @@ private fun WeekDayHeader(
}
}
/** Calendar-week badge shown in the header gutter, deliberately set apart with a
* filled box and bold number. */
@Composable
private fun WeekNumberBadge(weekNumber: Int, modifier: Modifier = Modifier) {
val label = stringResource(R.string.week_number_label)
Surface(
shape = RoundedCornerShape(8.dp),
color = MaterialTheme.colorScheme.secondaryContainer,
contentColor = MaterialTheme.colorScheme.onSecondaryContainer,
modifier = modifier.semantics { contentDescription = "$label $weekNumber" },
) {
Text(
text = weekNumber.toString(),
style = MaterialTheme.typography.titleSmall,
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp),
)
}
}
@Composable
private fun AllDayStrip(
state: WeekUiState.Success,