Refactor the quest detail layout (spacing).

This commit is contained in:
Thomas Andres Gomez 2023-12-17 14:36:00 +01:00
parent 00267623ca
commit 8acb98ac27

View file

@ -18,6 +18,7 @@ import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.minimumInteractiveComponentSize
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton 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.platform.LocalView
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow 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.navigateToLexiconDetail
import com.pixelized.rplexicon.ui.navigation.screens.navigateToLocationDetail import com.pixelized.rplexicon.ui.navigation.screens.navigateToLocationDetail
import com.pixelized.rplexicon.ui.theme.LexiconTheme 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_FULL
import com.pixelized.rplexicon.utilitary.LOS_HOLLOW import com.pixelized.rplexicon.utilitary.LOS_HOLLOW
import com.pixelized.rplexicon.utilitary.annotate import com.pixelized.rplexicon.utilitary.annotate
@ -153,7 +156,7 @@ private fun QuestDetailContent(
}, },
content = { padding -> content = { padding ->
Surface( Surface(
modifier = Modifier.padding(padding), modifier = Modifier.padding(paddingValues = padding),
) { ) {
Box( Box(
modifier = Modifier modifier = Modifier
@ -177,6 +180,7 @@ private fun QuestDetailContent(
) )
} }
} }
Column( Column(
modifier = Modifier modifier = Modifier
.verticalScroll(state) .verticalScroll(state)
@ -188,13 +192,13 @@ private fun QuestDetailContent(
}, },
bottom = 16.dp, bottom = 16.dp,
), ),
verticalArrangement = Arrangement.spacedBy(space = 16.dp), verticalArrangement = Arrangement.spacedBy(space = 24.dp),
) { ) {
Text( Text(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 16.dp) .padding(horizontal = 16.dp)
.padding(bottom = 16.dp), .padding(bottom = 24.dp),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = typography.base.headlineLarge, style = typography.base.headlineLarge,
text = annotate( text = annotate(
@ -205,148 +209,15 @@ private fun QuestDetailContent(
) )
quest?.steps?.forEach { quest -> quest?.steps?.forEach { quest ->
Column( QuestStep(
verticalArrangement = Arrangement.spacedBy(8.dp), quest = quest,
) { typography = typography,
quest.subtitle?.let { highlightRegex = highlightRegex,
Text( dropCapRegex = dropCapRegex,
modifier = Modifier onGiver = onGiver,
.padding(horizontal = 16.dp) onLocation = onLocation,
.padding(top = 16.dp), onImage = onImage,
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,
),
) )
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 @Composable
private fun rememberMaxWidth(): Dp { private fun rememberMaxWidth(): Dp {
val configuration = LocalConfiguration.current val configuration = LocalConfiguration.current