Skip to content

Commit

Permalink
set up sectioned lists better
Browse files Browse the repository at this point in the history
start adding support for selected states in the rank selector
  • Loading branch information
PerrigoGames committed Jan 29, 2025
1 parent 2e9d5c1 commit 3d87944
Show file tree
Hide file tree
Showing 11 changed files with 189 additions and 95 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.perrigogames.life4.feature.ladder.*
import com.perrigogames.life4.util.ViewState
import dev.icerock.moko.mvvm.createViewModelFactory
import dev.icerock.moko.resources.compose.colorResource
import dev.icerock.moko.resources.desc.StringDesc

@Composable
fun LadderGoalsScreen(
Expand Down Expand Up @@ -60,28 +61,97 @@ fun LadderGoals(
onHiddenChanged: (Long) -> Unit,
// onExpandChanged: (Long) -> Unit,
modifier: Modifier = Modifier,
) {
when (val goals = data.goals) {
is UILadderGoals.SingleList -> {
SingleGoalList(
goals = goals,
allowCompleting = data.allowCompleting,
allowHiding = data.allowHiding,
onCompletedChanged = onCompletedChanged,
onHiddenChanged = onHiddenChanged,
modifier = modifier,
)
}
is UILadderGoals.CategorizedList -> {
CategorizedList(
goals = goals,
allowCompleting = data.allowCompleting,
allowHiding = data.allowHiding,
onCompletedChanged = onCompletedChanged,
onHiddenChanged = onHiddenChanged,
modifier = modifier,
)
}
}
}

@Composable
fun SingleGoalList(
goals: UILadderGoals.SingleList,
allowCompleting: Boolean,
allowHiding: Boolean,
onCompletedChanged: (Long) -> Unit,
onHiddenChanged: (Long) -> Unit,
modifier: Modifier = Modifier,
) {
LazyColumn(
modifier = modifier,
contentPadding = PaddingValues(all = 8.dp),
) {
when (val goals = data.goals) {
is UILadderGoals.SingleList -> {
itemsIndexed(goals.items) { idx, goal ->
if (idx > 0) {
SizedSpacer(size = 4.dp)
}
itemsIndexed(goals.items) { idx, goal ->
if (idx > 0) {
SizedSpacer(size = 4.dp)
}
LadderGoalItem(
goal = goal,
allowCompleting = allowCompleting,
allowHiding = allowHiding,
onCompletedChanged = onCompletedChanged,
onHiddenChanged = onHiddenChanged,
modifier = Modifier.fillParentMaxWidth(),
)
}
}
}

@Composable
fun CategorizedList(
goals: UILadderGoals.CategorizedList,
allowCompleting: Boolean,
allowHiding: Boolean,
onCompletedChanged: (Long) -> Unit,
onHiddenChanged: (Long) -> Unit,
modifier: Modifier = Modifier,
) {
val context = LocalContext.current
val aggregateItems = goals.categories
.flatMap { (title, goals) -> listOf(title) + goals }
LazyColumn(
modifier = modifier,
contentPadding = PaddingValues(all = 8.dp),
) {
itemsIndexed(aggregateItems) { idx, item ->
if (idx > 0) {
SizedSpacer(size = 4.dp)
}
when(item) {
is StringDesc -> {
Text(
text = item.toString(context)
)
}
is UILadderGoal -> {
LadderGoalItem(
goal = goal,
allowCompleting = data.allowCompleting,
allowHiding = data.allowHiding,
goal = item,
allowCompleting = allowCompleting,
allowHiding = allowHiding,
onCompletedChanged = onCompletedChanged,
onHiddenChanged = onHiddenChanged,
modifier = Modifier.fillParentMaxWidth(),
)
}
}
is UILadderGoals.CategorizedList -> item { Text("FIXME") }
}
}
}
Expand Down Expand Up @@ -184,7 +254,7 @@ private fun LadderGoalHeaderRow(
onCheckedChange = { onCompletedChanged(goal.id) },
)
}
if (allowHiding) { // FIXME these should be fixed so they have a state when we show these too
if (allowHiding && goal.canHide) { // FIXME these should be fixed so they have a state when we show these too
Icon(
painter = painterResource(R.drawable.ic_eye),
tint = MaterialTheme.colorScheme.onSurface,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fun RankSelection(
items(data.rankClasses) { category ->
RankCategoryImage(
category = category,

onClick = { onInput(category.tapInput) },
)
SizedSpacer(size = Paddings.LARGE)
Expand Down Expand Up @@ -190,6 +191,7 @@ private fun RankCategoryImage(
RankImageWithTitle(
rank = category.rankClass?.toLadderRank(),
iconSize = 64.dp,
selected = category.selected,
text = stringResource(category.text),
style = MaterialTheme.typography.titleSmall,
onClick = onClick
Expand All @@ -200,6 +202,7 @@ private fun RankCategoryImage(
fun RankSelectionMini(
modifier: Modifier = Modifier,
ranks: List<LadderRank> = LadderRank.entries,
selectedRank: LadderRank?,
showNone: Boolean = true,
onRankSelected: (LadderRank?) -> Unit,
) {
Expand All @@ -212,12 +215,16 @@ fun RankSelectionMini(
}
if (showNone) {
item {
RankImageWithTitle(rank = null)
RankImageWithTitle(
rank = null,
selected = selectedRank == null
)
}
}
items(ranks) { rank ->
RankImageWithTitle(
rank = rank,
selected = rank == selectedRank,
onClick = { onRankSelected(rank) }
)
}
Expand All @@ -243,6 +250,7 @@ fun RankSelectionMiniPreview() {
LIFE4Theme {
Surface {
RankSelectionMini(
selectedRank = null,
onRankSelected = {}
)
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,14 @@ data class LadderRankData(
}
}

private fun mapIdsToGoals(ids: List<Int>): List<BaseRankGoal> {
private fun mapIdsToGoals(
ids: List<Int>,
): List<BaseRankGoal> {
return ids.map { id ->
wrappedGoals.firstOrNull { it.id == id } ?:
goals.firstOrNull { it.id == id } ?:
error("ID not found: $id")
wrappedGoals.firstOrNull { it.id == id }
?: goals.firstOrNull { it.id == id }
?: error("ID not found: $id")

}
}

Expand All @@ -79,9 +82,9 @@ data class LadderVersion(
data class RankEntry(
val rank: LadderRank,
@SerialName("play_style") val playStyle: PlayStyle,
@SerialName("goal_ids") val goalIds: List<Int>? = null,
@SerialName("mandatory_goal_ids") val mandatoryGoalIds: List<Int>? = null,
val substitutions: List<Int>? = null,
@SerialName("goal_ids") val goalIds: List<Int> = emptyList(),
@SerialName("mandatory_goal_ids") val mandatoryGoalIds: List<Int> = emptyList(),
val substitutions: List<Int> = emptyList(),
@SerialName("requirements") private val requirementsOpt: Int? = null,
) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ import org.koin.core.component.KoinComponent
@Serializable
sealed class BaseRankGoal {

@Transient var isMandatory: Boolean = false

abstract val id: Int
@SerialName("s") open val playStyle: PlayStyle = PlayStyle.SINGLE

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.perrigogames.life4.feature.ladder

import co.touchlab.kermit.Logger
import com.perrigogames.life4.MR
import com.perrigogames.life4.data.BaseRankGoal
import com.perrigogames.life4.data.RankEntry
import com.perrigogames.life4.data.SongsClearGoal
import com.perrigogames.life4.enums.GoalStatus
import com.perrigogames.life4.enums.LadderRank
import com.perrigogames.life4.feature.profile.UserRankManager
Expand All @@ -17,6 +20,9 @@ import dev.icerock.moko.mvvm.flow.CStateFlow
import dev.icerock.moko.mvvm.flow.cMutableStateFlow
import dev.icerock.moko.mvvm.flow.cStateFlow
import dev.icerock.moko.mvvm.viewmodel.ViewModel
import dev.icerock.moko.resources.desc.ResourceFormatted
import dev.icerock.moko.resources.desc.StringDesc
import dev.icerock.moko.resources.desc.desc
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.launch
import org.koin.core.component.KoinComponent
Expand Down Expand Up @@ -56,18 +62,59 @@ class GoalListViewModel(private val config: GoalListConfig) : ViewModel(), KoinC
when {
targetRank == null -> ViewState.Error("No higher goals found...")
requirements == null -> ViewState.Error("No goals found for ${targetRank.name}")
targetRank >= LadderRank.PLATINUM1 -> ViewState.Success(
UILadderData(
goals = generateDifficultyCategories(requirements)
)
)
else -> ViewState.Success(
UILadderData(
goals = UILadderGoals.SingleList(
items = requirements.goals.map(ladderGoalMapper::toViewData)
)
goals = generateCommonCategories(requirements)
)
)
}
}.collect { _state.value = it }
}
}

private fun generateCommonCategories(requirements: RankEntry) : UILadderGoals.CategorizedList {
return UILadderGoals.CategorizedList(
categories = listOf(
MR.strings.goals.desc() to
requirements.goals.map { ladderGoalMapper.toViewData(it, isMandatory = false) },
MR.strings.mandatory_goals.desc() to
requirements.mandatoryGoals.map { ladderGoalMapper.toViewData(it, isMandatory = true) }
)
)
}

private fun generateDifficultyCategories(requirements: RankEntry) : UILadderGoals.CategorizedList {
val songsClearGoals = requirements.allGoals.filterIsInstance<SongsClearGoal>()
val remainingGoals = requirements.allGoals.filterNot { it is SongsClearGoal }
val categories = (songsClearGoals.groupBy { it.diffNum }
.toList()
as List<Pair<Int?, List<BaseRankGoal>>>)
.sortedBy { it.first ?: Int.MAX_VALUE }
.toMutableList()
val otherIndex = categories.indexOfFirst { it.first == null }
if (categories.any { it.first == null }) {
val otherGoals = categories.removeAt(otherIndex).second
categories.add(otherIndex, null to (otherGoals + remainingGoals))
} else {
categories.add(null to remainingGoals)
}

return UILadderGoals.CategorizedList(
categories = categories.map { (level, goals) ->
val title = level?.let { StringDesc.ResourceFormatted(MR.strings.level_header, it) }
?: MR.strings.other_goals.desc()
title to goals.map {
ladderGoalMapper.toViewData(it, isMandatory = requirements.mandatoryGoalIds.contains(it.id))
}
}
)
}

fun handleAction(action: RankListAction) = when(action) {
is RankListAction.OnGoal -> {
val goal = entry?.allGoals?.firstOrNull { it.id.toLong() == action.id }.ifNull { return }
Expand Down Expand Up @@ -102,7 +149,7 @@ class GoalListViewModel(private val config: GoalListConfig) : ViewModel(), KoinC
private fun updateGoal(id: Long) {
val baseGoal = findGoal(id.toInt()).ifNull { return }
modifyGoal(id) {
ladderGoalMapper.toViewData(baseGoal!!)
ladderGoalMapper.toViewData(baseGoal!!, isMandatory = it.isMandatory)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class RankListViewModel(
ladderData = goalEntry?.allGoals?.let { goals ->
UILadderData(
items = goals.map { goal ->
ladderGoalMapper.toViewData(goal)
ladderGoalMapper.toViewData(goal, isMandatory = goalEntry.mandatoryGoalIds.contains(goal.id))
},
allowCompleting = false,
allowHiding = false
Expand Down
Loading

0 comments on commit 3d87944

Please sign in to comment.