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.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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue