Give the day and week timelines an end inset (#192)

This commit is contained in:
2026-08-17 17:11:42 +02:00
parent 558aa2e69b
commit c7b3ff2d6f
3 changed files with 35 additions and 5 deletions

View File

@@ -36,6 +36,14 @@ val GUTTER_WIDTH = 48.dp
*/ */
val GUTTER_CONTENT_START_INSET = 8.dp val GUTTER_CONTENT_START_INSET = 8.dp
/**
* End inset for everything that lines up with the day columns — the week's day
* header, the all-day strip and the timeline itself. Without it the last column
* runs flush into the screen edge while the gutter gives the other side room
* (#192); 8dp mirrors [GUTTER_CONTENT_START_INSET].
*/
val TIMELINE_CONTENT_END_INSET = 8.dp
private val BADGE_HEIGHT = 20.dp private val BADGE_HEIGHT = 20.dp
/** How far the fixed hour labels recede while a block is being dragged. */ /** How far the fixed hour labels recede while a block is being dragged. */

View File

@@ -118,6 +118,7 @@ import de.jeanlucmakiola.calendula.ui.common.rememberTimelinePinchZoom
import de.jeanlucmakiola.calendula.ui.common.formatMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.formatMinuteOfDay
import de.jeanlucmakiola.calendula.ui.common.GUTTER_WIDTH import de.jeanlucmakiola.calendula.ui.common.GUTTER_WIDTH
import de.jeanlucmakiola.calendula.ui.common.HourGutter import de.jeanlucmakiola.calendula.ui.common.HourGutter
import de.jeanlucmakiola.calendula.ui.common.TIMELINE_CONTENT_END_INSET
import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines
import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay
import de.jeanlucmakiola.calendula.ui.week.TimedBlock import de.jeanlucmakiola.calendula.ui.week.TimedBlock
@@ -471,7 +472,11 @@ private fun AllDayStrip(
// Height is hoisted + animated so it resizes smoothly; padding sits // Height is hoisted + animated so it resizes smoothly; padding sits
// inside it so the content area is lanes * row height. // inside it so the content area is lanes * row height.
.height(height) .height(height)
.padding(vertical = ALL_DAY_VERTICAL_PADDING), .padding(
top = ALL_DAY_VERTICAL_PADDING,
bottom = ALL_DAY_VERTICAL_PADDING,
end = TIMELINE_CONTENT_END_INSET,
),
) { ) {
// Keep the gutter-width offset so the bars line up with the day column. // Keep the gutter-width offset so the bars line up with the day column.
Spacer(Modifier.width(GUTTER_WIDTH)) Spacer(Modifier.width(GUTTER_WIDTH))
@@ -570,6 +575,7 @@ private fun Timeline(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.fillMaxHeight() .fillMaxHeight()
.padding(end = TIMELINE_CONTENT_END_INSET)
.clip(RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp))
.verticalScroll(scrollState) .verticalScroll(scrollState)
.onGloballyPositioned { dragController.geometry.viewport = it }, .onGloballyPositioned { dragController.geometry.viewport = it },
@@ -792,7 +798,12 @@ private fun DayLoading() {
// Same scale resolution as the loaded timeline, so the skeleton's column // Same scale resolution as the loaded timeline, so the skeleton's column
// doesn't resize the moment the real day arrives. // doesn't resize the moment the real day arrives.
val totalHeight = scale.hourHeight(maxHeight) * 24 val totalHeight = scale.hourHeight(maxHeight) * 24
Row(modifier = Modifier.fillMaxSize().verticalScroll(scrollState)) { Row(
modifier = Modifier
.fillMaxSize()
.padding(end = TIMELINE_CONTENT_END_INSET)
.verticalScroll(scrollState),
) {
Spacer(Modifier.width(GUTTER_WIDTH)) Spacer(Modifier.width(GUTTER_WIDTH))
Box( Box(
modifier = Modifier modifier = Modifier

View File

@@ -129,6 +129,7 @@ import de.jeanlucmakiola.calendula.ui.common.formatMinuteOfDay
import de.jeanlucmakiola.calendula.ui.common.GUTTER_CONTENT_START_INSET import de.jeanlucmakiola.calendula.ui.common.GUTTER_CONTENT_START_INSET
import de.jeanlucmakiola.calendula.ui.common.GUTTER_WIDTH import de.jeanlucmakiola.calendula.ui.common.GUTTER_WIDTH
import de.jeanlucmakiola.calendula.ui.common.HourGutter import de.jeanlucmakiola.calendula.ui.common.HourGutter
import de.jeanlucmakiola.calendula.ui.common.TIMELINE_CONTENT_END_INSET
import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines import de.jeanlucmakiola.calendula.ui.common.hourSeparatorLines
import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay import de.jeanlucmakiola.calendula.ui.common.tappedMinuteOfDay
import de.jeanlucmakiola.calendula.ui.common.rememberCalendarSlideSpec import de.jeanlucmakiola.calendula.ui.common.rememberCalendarSlideSpec
@@ -506,7 +507,7 @@ private fun WeekDayHeader(
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 4.dp, bottom = 8.dp), .padding(top = 4.dp, bottom = 8.dp, end = TIMELINE_CONTENT_END_INSET),
) { ) {
// Mirror the day-column layout (empty weekday line + spacer) so the // Mirror the day-column layout (empty weekday line + spacer) so the
// badge lines up vertically with the date numbers. The start inset centres // badge lines up vertically with the date numbers. The start inset centres
@@ -602,7 +603,11 @@ private fun AllDayStrip(
// Height is hoisted + animated so it slides and resizes smoothly; // Height is hoisted + animated so it slides and resizes smoothly;
// padding sits inside it so the content area is lanes * row height. // padding sits inside it so the content area is lanes * row height.
.height(height) .height(height)
.padding(vertical = ALL_DAY_VERTICAL_PADDING), .padding(
top = ALL_DAY_VERTICAL_PADDING,
bottom = ALL_DAY_VERTICAL_PADDING,
end = TIMELINE_CONTENT_END_INSET,
),
) { ) {
// Keep the gutter-width offset so the bars line up with the day columns. // Keep the gutter-width offset so the bars line up with the day columns.
Spacer(Modifier.width(GUTTER_WIDTH)) Spacer(Modifier.width(GUTTER_WIDTH))
@@ -708,6 +713,7 @@ private fun Timeline(
modifier = Modifier modifier = Modifier
.weight(1f) .weight(1f)
.fillMaxHeight() .fillMaxHeight()
.padding(end = TIMELINE_CONTENT_END_INSET)
.clip(RoundedCornerShape(16.dp)) .clip(RoundedCornerShape(16.dp))
.verticalScroll(scrollState) .verticalScroll(scrollState)
.onGloballyPositioned { dragController.geometry.viewport = it }, .onGloballyPositioned { dragController.geometry.viewport = it },
@@ -977,7 +983,12 @@ private fun WeekLoading() {
// Same scale resolution as the loaded timeline, so the skeleton's // Same scale resolution as the loaded timeline, so the skeleton's
// columns don't resize the moment the real week arrives. // columns don't resize the moment the real week arrives.
val totalHeight = scale.hourHeight(maxHeight) * 24 val totalHeight = scale.hourHeight(maxHeight) * 24
Row(modifier = Modifier.fillMaxSize().verticalScroll(scrollState)) { Row(
modifier = Modifier
.fillMaxSize()
.padding(end = TIMELINE_CONTENT_END_INSET)
.verticalScroll(scrollState),
) {
Spacer(Modifier.width(GUTTER_WIDTH)) Spacer(Modifier.width(GUTTER_WIDTH))
repeat(7) { repeat(7) {
Box( Box(