From 067f82e5e2725ce79b35bade80bb71fbca1f1473 Mon Sep 17 00:00:00 2001 From: MaxsTechReview Date: Sun, 25 Oct 2026 12:59:58 -0400 Subject: [PATCH] fix(stores): let a game's description fill the free height of the page (#1493) Co-authored-by: Kurt Himebauch <136133082+xXJSONDeruloXx@users.noreply.github.com> --- .../java/com/droiddeck/launcher/ui/CardDetailHost.kt | 11 +++++++++-- .../main/java/com/droiddeck/launcher/ui/GameDetail.kt | 10 +++++++++- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/droiddeck/launcher/ui/CardDetailHost.kt b/app/src/main/java/com/droiddeck/launcher/ui/CardDetailHost.kt index d94ee25a7..f606e6008 100644 --- a/app/src/main/java/com/droiddeck/launcher/ui/CardDetailHost.kt +++ b/app/src/main/java/com/droiddeck/launcher/ui/CardDetailHost.kt @@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -37,6 +38,8 @@ import androidx.compose.runtime.setValue import androidx.compose.runtime.getValue /** A grid of cards with a game page that floods out of the opened card and drains back into it. */ +internal val LocalDetailFloor = compositionLocalOf<() -> Float> { { Float.MAX_VALUE } } + @OptIn(androidx.compose.ui.ExperimentalComposeUiApi::class) @Composable internal fun CardDetailHost( @@ -57,6 +60,7 @@ internal fun CardDetailHost( var from by remember { mutableStateOf(null) } var art by remember { mutableStateOf(null) } var viewportAt by remember { mutableStateOf(Offset.Zero) } + var viewportH by remember { mutableStateOf(0) } LaunchedEffect(open) { if (open != null) { val mark = StoresMotion.takeCard(open) @@ -83,7 +87,7 @@ internal fun CardDetailHost( val fade = with(density) { 14.dp.toPx() } Box( modifier.clipToBounds() - .onGloballyPositioned { viewportAt = it.positionInRoot() } + .onGloballyPositioned { viewportAt = it.positionInRoot(); viewportH = it.size.height } .graphicsLayer { compositingStrategy = androidx.compose.ui.graphics.CompositingStrategy.Offscreen } .drawWithContent { drawContent() @@ -114,7 +118,10 @@ internal fun CardDetailHost( .onFocusChanged { onDetailFocus(it.hasFocus) } .focusProperties { exit = { if (coveringNow.value && Steps.step == null && StoresMotion.step == null) FocusRequester.Cancel else FocusRequester.Default } } .focusGroup(), - ) { detail(key) } + ) { + val floor = { viewportAt.y + viewportH - with(density) { 16.dp.toPx() } - detailScroll.value } + CompositionLocalProvider(LocalDetailFloor provides floor) { detail(key) } + } } } val origin = from diff --git a/app/src/main/java/com/droiddeck/launcher/ui/GameDetail.kt b/app/src/main/java/com/droiddeck/launcher/ui/GameDetail.kt index 32be30564..7c9cdc74c 100644 --- a/app/src/main/java/com/droiddeck/launcher/ui/GameDetail.kt +++ b/app/src/main/java/com/droiddeck/launcher/ui/GameDetail.kt @@ -56,6 +56,8 @@ import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.boundsInRoot import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInRoot +import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag @@ -599,7 +601,13 @@ private fun AboutTab(developer: String, publisher: String, releaseDate: String, val parts = listOf(developer, publisher, com.droiddeck.launcher.stores.GameFacts.releaseLabel(releaseDate).orEmpty()).filter { it.isNotBlank() }.distinct() Text(parts.joinToString(" ยท "), fontSize = 13.sp, color = MaterialTheme.colorScheme.onSurfaceVariant, modifier = Modifier.readable()) } - if (description.isNotBlank()) StoreAbout(description, AboutHeight, Modifier.fillMaxWidth()) + if (description.isNotBlank()) { + val floor = LocalDetailFloor.current + val density = LocalDensity.current + var room by remember { mutableStateOf(AboutHeight) } + val fill = Modifier.onGloballyPositioned { c -> room = maxOf(AboutHeight, with(density) { (floor() - c.positionInRoot().y).toDp() - 14.dp }) } + StoreAbout(description, room, Modifier.fillMaxWidth().then(fill)) + } } }