fix(calendars): apply scaffold padding so month/week/day headers and collections list don't render behind the top app bar

The DisappearingScaffold places content at y=0 by design (so feeds scroll
behind the bar) and exposes the bar height via [LocalDisappearingScaffoldPadding]
for inner scrollables to consume. The static-headered grid views and the
collections list weren't reading that local, so:

- The week view's WeekStrip (day-number row) rendered behind the top bar.
- The month/year title and grid header sat behind the bar similarly.
- The collections LazyColumn's first card was clipped under the bar.

Fix:
- Add a small `Modifier.disappearingScaffoldPadding()` helper that applies
  the local padding. Month/week/day views opt in with one line.
- Collections LazyColumn uses `rememberFeedContentPadding(FeedPadding)`
  so cards inset on first render but still scroll behind the bar (matching
  the feed view's behaviour).
This commit is contained in:
Claude
2026-05-19 21:58:34 +00:00
parent 5116bc21ae
commit 0dea41602a
5 changed files with 52 additions and 1 deletions
@@ -56,11 +56,13 @@ import com.vitorpamplona.amethyst.commons.ui.feeds.FeedState
import com.vitorpamplona.amethyst.model.LocalCache
import com.vitorpamplona.amethyst.model.Note
import com.vitorpamplona.amethyst.ui.feeds.RefresheableBox
import com.vitorpamplona.amethyst.ui.layouts.rememberFeedContentPadding
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.screen.loggedIn.video.UserCardHeader
import com.vitorpamplona.amethyst.ui.stringRes
import com.vitorpamplona.amethyst.ui.theme.FeedPadding
import com.vitorpamplona.quartz.nip01Core.core.Address
import com.vitorpamplona.quartz.nip52Calendar.appt.day.CalendarDateSlotEvent
import com.vitorpamplona.quartz.nip52Calendar.appt.time.CalendarTimeSlotEvent
@@ -102,7 +104,12 @@ private fun CollectionsBody(
nav: INav,
) {
val items by loaded.feed.collectAsStateWithLifecycle()
LazyColumn(modifier = Modifier.fillMaxSize()) {
LazyColumn(
// Reserve top space for the surrounding [DisappearingScaffold]'s top bar — without this
// the first card scrolls under it on the initial render.
contentPadding = rememberFeedContentPadding(FeedPadding),
modifier = Modifier.fillMaxSize(),
) {
items(items.list, key = { it.idHex }) { note ->
CalendarCollectionCard(note, accountViewModel, nav)
}
@@ -95,6 +95,7 @@ fun CalendarDayView(
modifier =
Modifier
.fillMaxSize()
.disappearingScaffoldPadding()
.calendarSwipeNavigation(
key = visibleEpochDay,
onSwipeLeft = { visibleEpochDay = visibleDate.plusDays(1).toEpochDay() },
@@ -106,6 +106,7 @@ fun CalendarMonthView(
modifier =
Modifier
.fillMaxSize()
.disappearingScaffoldPadding()
.calendarSwipeNavigation(
key = visibleYear to visibleMonthValue,
onSwipeLeft = {
@@ -0,0 +1,41 @@
/*
* Copyright (c) 2025 Vitor Pamplona
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
* Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package com.vitorpamplona.amethyst.ui.screen.loggedIn.calendars
import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import com.vitorpamplona.amethyst.ui.layouts.LocalDisappearingScaffoldPadding
/**
* Applies the surrounding [com.vitorpamplona.amethyst.ui.layouts.DisappearingScaffold]'s reserved
* top/bottom space as padding. The scaffold places content at y=0 by design — it lets feeds
* scroll *behind* the disappearing bar — but the month/week/day views are static-headered grids,
* so without this modifier the grid header would render under the top app bar. Outside a
* scaffold the local default is zero and the modifier is a no-op.
*/
@Composable
fun Modifier.disappearingScaffoldPadding(): Modifier =
composed {
val padding = LocalDisappearingScaffoldPadding.current
this.padding(padding)
}
@@ -96,6 +96,7 @@ fun CalendarWeekView(
modifier =
Modifier
.fillMaxSize()
.disappearingScaffoldPadding()
.calendarSwipeNavigation(
key = weekStartEpochDay,
onSwipeLeft = {