Refactor the quest detail layout (spacing).
This commit is contained in:
		
							parent
							
								
									00267623ca
								
							
						
					
					
						commit
						8acb98ac27
					
				
					 1 changed files with 150 additions and 144 deletions
				
			
		| 
						 | 
				
			
			@ -18,6 +18,7 @@ import androidx.compose.foundation.lazy.LazyRow
 | 
			
		|||
import androidx.compose.foundation.lazy.items
 | 
			
		||||
import androidx.compose.foundation.rememberScrollState
 | 
			
		||||
import androidx.compose.foundation.verticalScroll
 | 
			
		||||
import androidx.compose.material.minimumInteractiveComponentSize
 | 
			
		||||
import androidx.compose.material3.ExperimentalMaterial3Api
 | 
			
		||||
import androidx.compose.material3.Icon
 | 
			
		||||
import androidx.compose.material3.IconButton
 | 
			
		||||
| 
						 | 
				
			
			@ -41,6 +42,7 @@ import androidx.compose.ui.platform.LocalConfiguration
 | 
			
		|||
import androidx.compose.ui.platform.LocalView
 | 
			
		||||
import androidx.compose.ui.res.painterResource
 | 
			
		||||
import androidx.compose.ui.res.stringResource
 | 
			
		||||
import androidx.compose.ui.text.AnnotatedString
 | 
			
		||||
import androidx.compose.ui.text.font.FontWeight
 | 
			
		||||
import androidx.compose.ui.text.style.TextAlign
 | 
			
		||||
import androidx.compose.ui.text.style.TextOverflow
 | 
			
		||||
| 
						 | 
				
			
			@ -59,6 +61,7 @@ import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
 | 
			
		|||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLexiconDetail
 | 
			
		||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLocationDetail
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
			
		||||
import com.pixelized.rplexicon.ui.theme.typography.LexiconTypography
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.LOS_FULL
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.LOS_HOLLOW
 | 
			
		||||
import com.pixelized.rplexicon.utilitary.annotate
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +156,7 @@ private fun QuestDetailContent(
 | 
			
		|||
        },
 | 
			
		||||
        content = { padding ->
 | 
			
		||||
            Surface(
 | 
			
		||||
                modifier = Modifier.padding(padding),
 | 
			
		||||
                modifier = Modifier.padding(paddingValues = padding),
 | 
			
		||||
            ) {
 | 
			
		||||
                Box(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
| 
						 | 
				
			
			@ -177,6 +180,7 @@ private fun QuestDetailContent(
 | 
			
		|||
                        )
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                Column(
 | 
			
		||||
                    modifier = Modifier
 | 
			
		||||
                        .verticalScroll(state)
 | 
			
		||||
| 
						 | 
				
			
			@ -188,13 +192,13 @@ private fun QuestDetailContent(
 | 
			
		|||
                            },
 | 
			
		||||
                            bottom = 16.dp,
 | 
			
		||||
                        ),
 | 
			
		||||
                    verticalArrangement = Arrangement.spacedBy(space = 16.dp),
 | 
			
		||||
                    verticalArrangement = Arrangement.spacedBy(space = 24.dp),
 | 
			
		||||
                ) {
 | 
			
		||||
                    Text(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .fillMaxWidth()
 | 
			
		||||
                            .padding(horizontal = 16.dp)
 | 
			
		||||
                            .padding(bottom = 16.dp),
 | 
			
		||||
                            .padding(bottom = 24.dp),
 | 
			
		||||
                        textAlign = TextAlign.Center,
 | 
			
		||||
                        style = typography.base.headlineLarge,
 | 
			
		||||
                        text = annotate(
 | 
			
		||||
| 
						 | 
				
			
			@ -205,148 +209,15 @@ private fun QuestDetailContent(
 | 
			
		|||
                    )
 | 
			
		||||
 | 
			
		||||
                    quest?.steps?.forEach { quest ->
 | 
			
		||||
                        Column(
 | 
			
		||||
                            verticalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
                        ) {
 | 
			
		||||
                            quest.subtitle?.let {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    modifier = Modifier
 | 
			
		||||
                                        .padding(horizontal = 16.dp)
 | 
			
		||||
                                        .padding(top = 16.dp),
 | 
			
		||||
                                    style = MaterialTheme.typography.titleLarge,
 | 
			
		||||
                                    textAlign = TextAlign.Center,
 | 
			
		||||
                                    overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                                    maxLines = 3,
 | 
			
		||||
                                    text = annotate(
 | 
			
		||||
                                        text = it,
 | 
			
		||||
                                        dropCapRegex styleWith typography.titleLargeDropCap,
 | 
			
		||||
                                        highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                                    ),
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
 | 
			
		||||
                            quest.giver?.let {
 | 
			
		||||
                                Column(
 | 
			
		||||
                                    modifier = Modifier
 | 
			
		||||
                                        .fillMaxWidth()
 | 
			
		||||
                                        .clickable(
 | 
			
		||||
                                            enabled = quest.giverId != null,
 | 
			
		||||
                                            onClick = { quest.giverId?.let { onGiver(it) } }
 | 
			
		||||
                                        )
 | 
			
		||||
                                        .padding(horizontal = 16.dp)
 | 
			
		||||
                                ) {
 | 
			
		||||
                                    Text(
 | 
			
		||||
                                        style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                                        fontWeight = FontWeight.Bold,
 | 
			
		||||
                                        text = stringResource(id = R.string.quest_detail_giver),
 | 
			
		||||
                                    )
 | 
			
		||||
                                    Text(
 | 
			
		||||
                                        style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                                        text = annotate(
 | 
			
		||||
                                            text = when (quest.giverId) {
 | 
			
		||||
                                                null -> "$LOS_HOLLOW $it"
 | 
			
		||||
                                                else -> "$LOS_FULL $it"
 | 
			
		||||
                                            },
 | 
			
		||||
                                            highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                                        )
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        quest.place?.let {
 | 
			
		||||
                            Column(
 | 
			
		||||
                                modifier = Modifier
 | 
			
		||||
                                    .fillMaxWidth()
 | 
			
		||||
                                    .clickable(
 | 
			
		||||
                                        enabled = quest.placeId != null,
 | 
			
		||||
                                        onClick = { quest.placeId?.let { onLocation(it) } }
 | 
			
		||||
                                    )
 | 
			
		||||
                                    .padding(horizontal = 16.dp),
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                                    fontWeight = FontWeight.Bold,
 | 
			
		||||
                                    text = stringResource(id = R.string.quest_detail_area),
 | 
			
		||||
                                )
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                                    text = annotate(
 | 
			
		||||
                                        text = when (quest.placeId) {
 | 
			
		||||
                                            null -> "$LOS_HOLLOW $it"
 | 
			
		||||
                                            else -> "$LOS_FULL $it"
 | 
			
		||||
                                        },
 | 
			
		||||
                                        highlightRegex styleWith typography.detail.highlightStyle
 | 
			
		||||
                                    ),
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        quest.globalReward?.let {
 | 
			
		||||
                            Column(
 | 
			
		||||
                                modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                                    fontWeight = FontWeight.Bold,
 | 
			
		||||
                                    text = stringResource(id = R.string.quest_detail_group_reward),
 | 
			
		||||
                                )
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                                    text = annotate(
 | 
			
		||||
                                        text = "$LOS_HOLLOW $it",
 | 
			
		||||
                                        highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                                    ),
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        quest.individualReward?.let {
 | 
			
		||||
                            Column(
 | 
			
		||||
                                modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                            ) {
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
                                    fontWeight = FontWeight.Bold,
 | 
			
		||||
                                    text = stringResource(id = R.string.quest_detail_individual_reward),
 | 
			
		||||
                                )
 | 
			
		||||
                                Text(
 | 
			
		||||
                                    style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                                    text = annotate(
 | 
			
		||||
                                        text = "$LOS_HOLLOW $it",
 | 
			
		||||
                                        highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                                    ),
 | 
			
		||||
                                )
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        Text(
 | 
			
		||||
                            modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
                            style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
                            text = annotate(
 | 
			
		||||
                                text = quest.description,
 | 
			
		||||
                                dropCapRegex styleWith typography.bodyMediumDropCap,
 | 
			
		||||
                                highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                            ),
 | 
			
		||||
                        QuestStep(
 | 
			
		||||
                            quest = quest,
 | 
			
		||||
                            typography = typography,
 | 
			
		||||
                            highlightRegex = highlightRegex,
 | 
			
		||||
                            dropCapRegex = dropCapRegex,
 | 
			
		||||
                            onGiver = onGiver,
 | 
			
		||||
                            onLocation = onLocation,
 | 
			
		||||
                            onImage = onImage,
 | 
			
		||||
                        )
 | 
			
		||||
 | 
			
		||||
                        if (quest.images.isNotEmpty()) {
 | 
			
		||||
                            LazyRow(
 | 
			
		||||
                                contentPadding = PaddingValues(horizontal = 16.dp),
 | 
			
		||||
                                horizontalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
                            ) {
 | 
			
		||||
                                items(items = quest.images) {
 | 
			
		||||
                                    AsyncImage(
 | 
			
		||||
                                        modifier = Modifier
 | 
			
		||||
                                            .clickable { onImage(it) }
 | 
			
		||||
                                            .sizeIn(maxWidth = rememberMaxWidth())
 | 
			
		||||
                                            .height(height = 160.dp),
 | 
			
		||||
                                        contentScale = ContentScale.FillHeight,
 | 
			
		||||
                                        model = it,
 | 
			
		||||
                                    )
 | 
			
		||||
                                }
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -354,6 +225,141 @@ private fun QuestDetailContent(
 | 
			
		|||
    )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun QuestStep(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    quest: QuestDetailUio.QuestStep,
 | 
			
		||||
    typography: LexiconTypography,
 | 
			
		||||
    highlightRegex: Regex,
 | 
			
		||||
    dropCapRegex: Regex,
 | 
			
		||||
    onGiver: (String) -> Unit,
 | 
			
		||||
    onLocation: (String) -> Unit,
 | 
			
		||||
    onImage: (Uri) -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = modifier,
 | 
			
		||||
        verticalArrangement = Arrangement.spacedBy(space = 8.dp)
 | 
			
		||||
    ) {
 | 
			
		||||
        quest.subtitle?.let {
 | 
			
		||||
            Text(
 | 
			
		||||
                modifier = Modifier
 | 
			
		||||
                    .padding(horizontal = 16.dp)
 | 
			
		||||
                    .padding(top = 16.dp),
 | 
			
		||||
                style = MaterialTheme.typography.titleLarge,
 | 
			
		||||
                textAlign = TextAlign.Center,
 | 
			
		||||
                overflow = TextOverflow.Ellipsis,
 | 
			
		||||
                maxLines = 3,
 | 
			
		||||
                text = annotate(
 | 
			
		||||
                    text = it,
 | 
			
		||||
                    dropCapRegex styleWith typography.titleLargeDropCap,
 | 
			
		||||
                    highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        quest.giver?.let {
 | 
			
		||||
            SubTitle(
 | 
			
		||||
                title = stringResource(id = R.string.quest_detail_giver),
 | 
			
		||||
                label = annotate(
 | 
			
		||||
                    text = when (quest.giverId) {
 | 
			
		||||
                        null -> "$LOS_HOLLOW $it"
 | 
			
		||||
                        else -> "$LOS_FULL $it"
 | 
			
		||||
                    },
 | 
			
		||||
                    highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                ),
 | 
			
		||||
                onClick = { quest.giverId?.let { id -> onGiver(id) } },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        quest.place?.let {
 | 
			
		||||
            SubTitle(
 | 
			
		||||
                title = stringResource(id = R.string.quest_detail_area),
 | 
			
		||||
                label = annotate(
 | 
			
		||||
                    text = when (quest.placeId) {
 | 
			
		||||
                        null -> "$LOS_HOLLOW $it"
 | 
			
		||||
                        else -> "$LOS_FULL $it"
 | 
			
		||||
                    },
 | 
			
		||||
                    highlightRegex styleWith typography.detail.highlightStyle
 | 
			
		||||
                ),
 | 
			
		||||
                onClick = { quest.placeId?.let { id -> onLocation(id) } },
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        quest.globalReward?.let {
 | 
			
		||||
            SubTitle(
 | 
			
		||||
                title = stringResource(id = R.string.quest_detail_group_reward),
 | 
			
		||||
                label = annotate(
 | 
			
		||||
                    text = "$LOS_HOLLOW $it",
 | 
			
		||||
                    highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        quest.individualReward?.let {
 | 
			
		||||
            SubTitle(
 | 
			
		||||
                title = stringResource(id = R.string.quest_detail_individual_reward),
 | 
			
		||||
                label = annotate(
 | 
			
		||||
                    text = "$LOS_HOLLOW $it",
 | 
			
		||||
                    highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
                ),
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        Text(
 | 
			
		||||
            modifier = Modifier.padding(horizontal = 16.dp),
 | 
			
		||||
            style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
            text = annotate(
 | 
			
		||||
                text = quest.description,
 | 
			
		||||
                dropCapRegex styleWith typography.bodyMediumDropCap,
 | 
			
		||||
                highlightRegex styleWith typography.detail.highlightStyle,
 | 
			
		||||
            ),
 | 
			
		||||
        )
 | 
			
		||||
        if (quest.images.isNotEmpty()) {
 | 
			
		||||
            LazyRow(
 | 
			
		||||
                contentPadding = PaddingValues(horizontal = 16.dp),
 | 
			
		||||
                horizontalArrangement = Arrangement.spacedBy(8.dp),
 | 
			
		||||
            ) {
 | 
			
		||||
                items(items = quest.images) {
 | 
			
		||||
                    AsyncImage(
 | 
			
		||||
                        modifier = Modifier
 | 
			
		||||
                            .clickable { onImage(it) }
 | 
			
		||||
                            .sizeIn(maxWidth = rememberMaxWidth())
 | 
			
		||||
                            .height(height = 160.dp),
 | 
			
		||||
                        contentScale = ContentScale.FillHeight,
 | 
			
		||||
                        model = it,
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun SubTitle(
 | 
			
		||||
    modifier: Modifier = Modifier,
 | 
			
		||||
    title: String,
 | 
			
		||||
    label: AnnotatedString,
 | 
			
		||||
    onClick: (() -> Unit)? = null,
 | 
			
		||||
) {
 | 
			
		||||
    Column(
 | 
			
		||||
        modifier = Modifier
 | 
			
		||||
            .clickable(
 | 
			
		||||
                enabled = onClick != null,
 | 
			
		||||
                onClick = { onClick?.invoke() }
 | 
			
		||||
            )
 | 
			
		||||
            .minimumInteractiveComponentSize()
 | 
			
		||||
            .fillMaxWidth()
 | 
			
		||||
            .padding(horizontal = 16.dp)
 | 
			
		||||
            .then(other = modifier),
 | 
			
		||||
        verticalArrangement = Arrangement.Center,
 | 
			
		||||
    ) {
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.titleMedium,
 | 
			
		||||
            fontWeight = FontWeight.Bold,
 | 
			
		||||
            text = title,
 | 
			
		||||
        )
 | 
			
		||||
        Text(
 | 
			
		||||
            style = MaterialTheme.typography.bodyMedium,
 | 
			
		||||
            text = label,
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
private fun rememberMaxWidth(): Dp {
 | 
			
		||||
    val configuration = LocalConfiguration.current
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue