Skip to content

Commit

Permalink
Implement monster detail paging (#322)
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandregpereira authored Aug 17, 2024
1 parent e38c514 commit 46a636e
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,23 @@ private fun LazyListScope.monsterInfoPart1(
}
}
item(key = "speed") {
MonsterRequireSectionAlphaTransition(
monsters,
pagerState,
MonsterOptionalSectionAlphaTransition(
dataList = monsters,
pagerState = pagerState,
getItemsKeys = getItemsKeys,
valueToValidate = { it.speed.values.isNotEmpty() },
) { monster ->
SpeedBlock(speed = monster.speed)
}
}
item(key = "abilityScores") {
MonsterRequireSectionAlphaTransition(
monsters,
pagerState,
ListOptionalSectionAlphaTransition(
dataList = monsters,
pagerState = pagerState,
getItemsKeys = getItemsKeys,
) { monster ->
AbilityScoreBlock(abilityScores = monster.abilityScores)
valueToValidate = { it.abilityScores }
) { abilityScores ->
AbilityScoreBlock(abilityScores = abilityScores)
}
}
}
Expand All @@ -146,7 +148,7 @@ private fun LazyListScope.monsterInfoPart2(
getItemsKeys: () -> List<Any> = { emptyList() },
) {
item(key = "savingThrows") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.savingThrows },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -165,7 +167,7 @@ private fun LazyListScope.monsterInfoPart2(
}
}
item(key = "skills") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.skills },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -185,7 +187,7 @@ private fun LazyListScope.monsterInfoPart3(
getItemsKeys: () -> List<Any> = { emptyList() },
) {
item(key = "damageVulnerabilities") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.damageVulnerabilities },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -195,7 +197,7 @@ private fun LazyListScope.monsterInfoPart3(
}
}
item(key = "damageResistances") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.damageResistances },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -205,7 +207,7 @@ private fun LazyListScope.monsterInfoPart3(
}
}
item(key = "damageImmunities") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.damageImmunities },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -215,7 +217,7 @@ private fun LazyListScope.monsterInfoPart3(
}
}
item(key = "conditionImmunities") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.conditionImmunities },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -233,16 +235,16 @@ private fun LazyListScope.monsterInfoPart4(
) {
item(key = "senses") {
MonsterOptionalSectionAlphaTransition(
valueToValidate = { it.senses },
valueToValidate = { monster -> monster.senses.all { it.isNotBlank() } },
dataList = monsters,
pagerState = pagerState,
getItemsKeys = getItemsKeys,
) {
SensesBlock(senses = it)
SensesBlock(senses = it.senses)
}
}
item(key = "languages") {
MonsterOptionalSectionAlphaTransition(
StringOptionalSectionAlphaTransition(
valueToValidate = { it.languages },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -262,7 +264,7 @@ private fun LazyListScope.monsterInfoPart5(
getItemsKeys: () -> List<Any> = { emptyList() },
) {
item(key = "specialAbilities") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.specialAbilities },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -273,7 +275,7 @@ private fun LazyListScope.monsterInfoPart5(
}

item(key = "actions") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.actions },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -284,7 +286,7 @@ private fun LazyListScope.monsterInfoPart5(
}

item(key = "reactions") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.reactions },
dataList = monsters,
pagerState = pagerState,
Expand All @@ -295,7 +297,7 @@ private fun LazyListScope.monsterInfoPart5(
}

item(key = "legendaryActions") {
MonsterOptionalSectionAlphaTransition(
ListOptionalSectionAlphaTransition(
valueToValidate = { it.legendaryActions },
dataList = monsters,
pagerState = pagerState,
Expand Down Expand Up @@ -352,19 +354,55 @@ internal fun LazyItemScope.MonsterRequireSectionAlphaTransition(
}

@Composable
internal fun <T> LazyItemScope.MonsterOptionalSectionAlphaTransition(
valueToValidate: (MonsterState) -> T,
internal fun LazyItemScope.MonsterOptionalSectionAlphaTransition(
valueToValidate: (MonsterState) -> Boolean,
dataList: List<MonsterState>,
pagerState: PagerState,
modifier: Modifier = Modifier,
getItemsKeys: () -> List<Any> = { emptyList() },
showDivider: Boolean = true,
content: @Composable ColumnScope.(MonsterState) -> Unit
) = MonsterSectionAlphaTransition(
dataList, pagerState, modifier.animateItemPlacement(), getItemsKeys
) { monster ->
OptionalBlockSection(isValid = { valueToValidate(monster) }, showDivider = showDivider) {
content(monster)
}
}

@Composable
internal fun <T> LazyItemScope.ListOptionalSectionAlphaTransition(
valueToValidate: (MonsterState) -> List<T>,
dataList: List<MonsterState>,
pagerState: PagerState,
modifier: Modifier = Modifier,
getItemsKeys: () -> List<Any> = { emptyList() },
showDivider: Boolean = true,
content: @Composable ColumnScope.(T) -> Unit
content: @Composable ColumnScope.(List<T>) -> Unit
) = MonsterSectionAlphaTransition(
dataList, pagerState, modifier.animateItemPlacement(), getItemsKeys
) { monster ->
OptionalBlockSection(valueToValidate(monster), showDivider = showDivider) { value ->
content(value)
val list = valueToValidate(monster)
OptionalBlockSection(isValid = { list.isNotEmpty() }, showDivider = showDivider) {
content(list)
}
}

@Composable
internal fun LazyItemScope.StringOptionalSectionAlphaTransition(
valueToValidate: (MonsterState) -> String,
dataList: List<MonsterState>,
pagerState: PagerState,
modifier: Modifier = Modifier,
getItemsKeys: () -> List<Any> = { emptyList() },
showDivider: Boolean = true,
content: @Composable ColumnScope.(String) -> Unit
) = MonsterSectionAlphaTransition(
dataList, pagerState, modifier.animateItemPlacement(), getItemsKeys
) { monster ->
val string = valueToValidate(monster)
OptionalBlockSection(isValid = { string.isNotBlank() }, showDivider = showDivider) {
content(string)
}
}

Expand All @@ -378,14 +416,14 @@ private fun MonsterInfoSectionColumn(
)

@Composable
private fun <T> ColumnScope.OptionalBlockSection(
value: T,
private fun ColumnScope.OptionalBlockSection(
isValid: () -> Boolean,
showDivider: Boolean = true,
content: @Composable ColumnScope.(T) -> Unit,
content: @Composable ColumnScope.() -> Unit,
) {
if ((value is String && value.trim().isEmpty()) || (value is List<*> && value.isEmpty())) return
if (isValid().not()) return
BlockSection(showDivider = showDivider) {
content(value)
content()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ data class MonsterState(
}
}

internal fun MonsterState.isComplete(): Boolean = abilityScores.isNotEmpty()

@ObjCName(name = "StatsState", exact = true)
data class StatsState(
val armorClass: Int = 0,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ class MonsterDetailStateHolder internal constructor(
private fun getMonstersByInitialIndex(
monsterIndex: String,
monsterIndexes: List<String>,
invalidateCache: Boolean = false
invalidateCache: Boolean = false,
loadingSubtle: Boolean = false,
) {
stateRecovery.saveMonsterIndexes(monsterIndexes)
onMonsterChanged(monsterIndex, scrolled = false)
Expand All @@ -154,7 +155,9 @@ class MonsterDetailStateHolder internal constructor(
.toMonsterDetailState()
.flowOn(dispatcher)
.onStart {
setState { copy(isLoading = true) }
if (loadingSubtle.not()) {
setState { copy(isLoading = true) }
}
}
.catch {
setState { copy(isLoading = false) }
Expand All @@ -170,13 +173,19 @@ class MonsterDetailStateHolder internal constructor(

fun onMonsterChanged(monsterIndex: String, scrolled: Boolean = true) {
if (scrolled && monsterIndex != this.monsterIndex) {
initialMonsterListPositionIndex = state.value.monsters.indexOfFirst {
it.index == monsterIndex
}.takeIf { it >= 0 } ?: initialMonsterListPositionIndex
val monsterPositionIndex = state.value.monsters.indexOfFirst { it.index == monsterIndex }
initialMonsterListPositionIndex = monsterPositionIndex.takeIf { it >= 0 }
?: initialMonsterListPositionIndex
if (enableMonsterPageChangesEventDispatch) {
analytics.trackMonsterPageChanged(monsterIndex, scrolled)
monsterEventDispatcher.dispatchEvent(OnMonsterPageChanges(monsterIndex))
}

state.value.monsters.getOrNull(monsterPositionIndex)?.let { monster ->
if (monster.isComplete().not()) {
getMonstersByInitialIndex(monsterIndex, monsterIndexes, loadingSubtle = true)
}
}
}
stateRecovery.saveMonsterIndex(monsterIndex)
}
Expand Down

0 comments on commit 46a636e

Please sign in to comment.