diff --git a/app/src/main/kotlin/com/subtracks/ui/components/ViewportFill.kt b/app/src/main/kotlin/com/subtracks/ui/components/ViewportFill.kt index 08ddcf63..055183e7 100644 --- a/app/src/main/kotlin/com/subtracks/ui/components/ViewportFill.kt +++ b/app/src/main/kotlin/com/subtracks/ui/components/ViewportFill.kt @@ -22,9 +22,9 @@ fun rememberViewportFill(state: LazyListState): Dp { if (realCount <= 0 || visibleReal.size < realCount) { FILL_EPSILON_PX } else { - val contentBottom = visibleReal.maxOf { it.offset + it.size } + val contentHeight = visibleReal.maxOf { it.offset + it.size } - visibleReal.minOf { it.offset } val padding = info.beforeContentPadding + info.afterContentPadding - (info.viewportSize.height - padding - contentBottom).coerceAtLeast(0) + FILL_EPSILON_PX + (info.viewportSize.height - padding - contentHeight).coerceAtLeast(0) + FILL_EPSILON_PX } } } @@ -42,9 +42,9 @@ fun rememberViewportFill(state: LazyGridState): Dp { if (realCount <= 0 || visibleReal.size < realCount) { FILL_EPSILON_PX } else { - val contentBottom = visibleReal.maxOf { it.offset.y + it.size.height } + val contentHeight = visibleReal.maxOf { it.offset.y + it.size.height } - visibleReal.minOf { it.offset.y } val padding = info.beforeContentPadding + info.afterContentPadding - (info.viewportSize.height - padding - contentBottom).coerceAtLeast(0) + FILL_EPSILON_PX + (info.viewportSize.height - padding - contentHeight).coerceAtLeast(0) + FILL_EPSILON_PX } } } diff --git a/app/src/test/kotlin/com/subtracks/ui/components/ViewportFillTest.kt b/app/src/test/kotlin/com/subtracks/ui/components/ViewportFillTest.kt new file mode 100644 index 00000000..be263c00 --- /dev/null +++ b/app/src/test/kotlin/com/subtracks/ui/components/ViewportFillTest.kt @@ -0,0 +1,58 @@ +package com.subtracks.ui.components + +import androidx.activity.ComponentActivity +import androidx.compose.foundation.gestures.scrollBy +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.material3.Text +import androidx.compose.ui.Modifier +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.test.junit4.v2.createAndroidComposeRule +import androidx.compose.ui.unit.dp +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.github.takahirom.roborazzi.RobolectricDeviceQualifiers +import com.subtracks.ui.theme.SubtracksTheme +import kotlinx.coroutines.runBlocking +import org.junit.Assert.assertEquals +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.robolectric.annotation.Config +import org.robolectric.annotation.GraphicsMode + +@RunWith(AndroidJUnit4::class) +@GraphicsMode(GraphicsMode.Mode.NATIVE) +@Config(qualifiers = RobolectricDeviceQualifiers.PixelXL) +class ViewportFillTest { + @get:Rule + val composeRule = createAndroidComposeRule() + + @Test + fun scrollingAShortListDoesNotGrowTheFill() { + lateinit var state: LazyListState + var fillHeight = 0 + composeRule.setContent { + SubtracksTheme { + state = rememberLazyListState() + val fill = rememberViewportFill(state) + LazyColumn(state = state, modifier = Modifier.fillMaxSize()) { + items(3) { Text("item $it", modifier = Modifier.height(56.dp)) } + item { Spacer(Modifier.height(fill).onSizeChanged { fillHeight = it.height }) } + } + } + } + composeRule.waitForIdle() + + val initial = fillHeight + repeat(4) { + composeRule.runOnIdle { runBlocking { state.scrollBy(4f) } } + composeRule.waitForIdle() + } + + assertEquals(initial, fillHeight) + } +}