From eaa4fcf8e92bd9fd667438aa6a2df5b9365c2295 Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Tue, 21 Nov 2023 15:28:18 +0100 Subject: [PATCH] Add background for quest screen. --- .../location/detail/LocationDetailScreen.kt | 192 ++++++++++-------- .../utilitary/extentions/ModifierEx.kt | 3 +- 2 files changed, 112 insertions(+), 83 deletions(-) diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/location/detail/LocationDetailScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/location/detail/LocationDetailScreen.kt index 694e36b..90dcd17 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/location/detail/LocationDetailScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/location/detail/LocationDetailScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.heightIn @@ -57,6 +58,7 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.input.nestedscroll.NestedScrollConnection import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalUriHandler @@ -67,12 +69,15 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.Velocity import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.min import androidx.hilt.navigation.compose.hiltViewModel import com.pixelized.rplexicon.LocalSnack import com.pixelized.rplexicon.R import com.pixelized.rplexicon.ui.composable.AsyncImage +import com.pixelized.rplexicon.ui.composable.BackgroundImage import com.pixelized.rplexicon.ui.composable.FullScreenImageHandler import com.pixelized.rplexicon.ui.composable.FullScreenImageViewModel import com.pixelized.rplexicon.ui.composable.rememberBackgroundGradient @@ -84,6 +89,7 @@ import com.pixelized.rplexicon.utilitary.annotate import com.pixelized.rplexicon.utilitary.annotateWithDropCap import com.pixelized.rplexicon.utilitary.dropCapRegex import com.pixelized.rplexicon.utilitary.extentions.lexicon +import com.pixelized.rplexicon.utilitary.extentions.scrollOffset import com.pixelized.rplexicon.utilitary.extentions.searchCriterion import com.pixelized.rplexicon.utilitary.highlightRegex import com.pixelized.rplexicon.utilitary.styleWith @@ -233,17 +239,22 @@ private fun LocationContent( val highlightRegex = remember(highlight) { highlightRegex(terms = highlight.searchCriterion()) } val dropCapRegex = remember { dropCapRegex() } + val mapSize = remember { mutableStateOf(null) } val filledIconButtonColors = IconButtonDefaults.filledIconButtonColors( containerColor = MaterialTheme.colorScheme.surface, contentColor = MaterialTheme.colorScheme.onSurface, ) - val filledIconToggleButtonColors = IconButtonDefaults.filledIconToggleButtonColors( containerColor = MaterialTheme.colorScheme.surface, contentColor = MaterialTheme.colorScheme.onSurface, checkedContainerColor = MaterialTheme.colorScheme.primary, checkedContentColor = MaterialTheme.colorScheme.onPrimary, ) + val backgroundUri = remember(item) { + derivedStateOf { + item.value?.illustrations?.firstOrNull() + } + } Scaffold( modifier = modifier, @@ -272,6 +283,7 @@ private fun LocationContent( ) { if (item.value?.map != null) { Surface( + modifier = Modifier.onSizeChanged { mapSize.value = it }, tonalElevation = 2.dp, ) { Box( @@ -386,105 +398,121 @@ private fun LocationContent( } } - Column( - modifier = Modifier - .fillMaxWidth() - .heightIn(min = this@constraint.maxHeight) - .padding(vertical = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(space = 24.dp), + Box( + modifier = Modifier.clip(RectangleShape), ) { - Text( - modifier = Modifier.padding(horizontal = 16.dp), - style = MaterialTheme.typography.headlineSmall, - text = annotate( - text = item.value?.name ?: "", - dropCapRegex styleWith typography.headlineSmallDropCap, - highlightRegex styleWith typography.detail.highlightStyle, - ), - ) - item.value?.description?.let { - Text( + backgroundUri.value?.let { uri -> + BackgroundImage( modifier = Modifier .fillMaxWidth() - .padding(horizontal = 16.dp), - style = MaterialTheme.typography.bodyMedium, + .aspectRatio(ratio = 1f) + .scrollOffset(scrollState = scrollState) { + val mapHeight = (mapSize.value?.height ?: 0).toDp() + min((mapHeight - it) / 2, 0.dp) + }, + model = uri, + ) + } + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn(min = this@constraint.maxHeight) + .padding(vertical = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(space = 24.dp), + ) { + Text( + modifier = Modifier.padding(horizontal = 16.dp), + style = MaterialTheme.typography.headlineSmall, text = annotate( - text = it, - dropCapRegex styleWith typography.bodyMediumDropCap, + text = item.value?.name ?: "", + dropCapRegex styleWith typography.headlineSmallDropCap, highlightRegex styleWith typography.detail.highlightStyle, ), ) - } - item.value?.illustrations?.takeIf { it.isNotEmpty() }?.let { - Column { - val maxSize = rememberMaxtWidth() + item.value?.description?.let { Text( modifier = Modifier - .padding(bottom = 8.dp) + .fillMaxWidth() .padding(horizontal = 16.dp), - style = MaterialTheme.typography.titleMedium, - text = annotateWithDropCap( - text = stringResource(id = R.string.map_illustrations), - style = MaterialTheme.lexicon.typography.titleMediumDropCap, - ) + style = MaterialTheme.typography.bodyMedium, + text = annotate( + text = it, + dropCapRegex styleWith typography.bodyMediumDropCap, + highlightRegex styleWith typography.detail.highlightStyle, + ), ) - LazyRow( - contentPadding = PaddingValues(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(8.dp), - ) { - items(items = it) { - AsyncImage( - modifier = Modifier - .clickable { onIllustration(it) } - .sizeIn( - minWidth = maxSize / 2, - maxWidth = maxSize, - minHeight = maxSize, - maxHeight = maxSize, - ), - contentScale = ContentScale.FillHeight, - model = it, + } + if (item.value?.marquees?.isNotEmpty() == true) { + Column { + Text( + modifier = Modifier + .padding(bottom = 8.dp) + .padding(horizontal = 16.dp), + style = MaterialTheme.typography.titleMedium, + text = annotateWithDropCap( + text = stringResource(id = R.string.map_destination), + style = MaterialTheme.lexicon.typography.titleMediumDropCap, ) + ) + item.value?.marquees?.forEach { + Row( + modifier = Modifier + .clickable { onDestination(it) } + .minimumInteractiveComponentSize() + .fillMaxWidth() + .padding(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(space = 8.dp), + ) { + Text( + modifier = Modifier.alignByBaseline(), + style = MaterialTheme.typography.bodyMedium, + text = LOS_FULL + ) + Text( + modifier = Modifier.alignByBaseline(), + style = MaterialTheme.typography.bodyMedium, + text = annotate( + text = it.name, + dropCapRegex styleWith typography.bodyMediumDropCap, + highlightRegex styleWith typography.detail.highlightStyle, + ), + ) + } } } } - } - if (item.value?.marquees?.isNotEmpty() == true) { - Column { - Text( - modifier = Modifier - .padding(bottom = 8.dp) - .padding(horizontal = 16.dp), - style = MaterialTheme.typography.titleMedium, - text = annotateWithDropCap( - text = stringResource(id = R.string.map_destination), - style = MaterialTheme.lexicon.typography.titleMediumDropCap, - ) - ) - item.value?.marquees?.forEach { - Row( + item.value?.illustrations?.takeIf { it.isNotEmpty() }?.let { + Column { + val maxSize = rememberMaxtWidth() + Text( modifier = Modifier - .clickable { onDestination(it) } - .minimumInteractiveComponentSize() - .fillMaxWidth() + .padding(bottom = 8.dp) .padding(horizontal = 16.dp), - horizontalArrangement = Arrangement.spacedBy(space = 8.dp), + style = MaterialTheme.typography.titleMedium, + text = annotateWithDropCap( + text = stringResource(id = R.string.map_illustrations), + style = MaterialTheme.lexicon.typography.titleMediumDropCap, + ) + ) + LazyRow( + contentPadding = PaddingValues(horizontal = 16.dp), + horizontalArrangement = Arrangement.spacedBy(8.dp), ) { - Text( - modifier = Modifier.alignByBaseline(), - style = MaterialTheme.typography.bodyMedium, - text = LOS_FULL - ) - Text( - modifier = Modifier.alignByBaseline(), - style = MaterialTheme.typography.bodyMedium, - text = annotate( - text = it.name, - dropCapRegex styleWith typography.bodyMediumDropCap, - highlightRegex styleWith typography.detail.highlightStyle, - ), - ) + items(items = it) { + AsyncImage( + modifier = Modifier + .clickable { onIllustration(it) } + .sizeIn( + minWidth = maxSize / 2, + maxWidth = maxSize, + minHeight = maxSize, + maxHeight = maxSize, + ), + contentScale = ContentScale.FillHeight, + model = it, + ) + } } } } diff --git a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt index 6ae9aac..83fb244 100644 --- a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt +++ b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt @@ -38,6 +38,7 @@ import androidx.compose.ui.graphics.TransformOrigin import androidx.compose.ui.graphics.graphicsLayer import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.google.accompanist.placeholder.PlaceholderHighlight @@ -99,7 +100,7 @@ fun Modifier.cell() = composed { @Stable fun Modifier.scrollOffset( scrollState: ScrollState, - block: (Dp) -> Dp + block: Density.(Dp) -> Dp ): Modifier = composed { val density = LocalDensity.current this.offset(y = with(density) { block(scrollState.value.toDp()) })