Skip to content

Commit

Permalink
Fix app crashing when clicking on monster folder preview
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandregpereira committed Aug 13, 2024
1 parent 23859db commit 4357ab3
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 86 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fun MonsterDetailFeature(

val viewModel: MonsterDetailStateHolder = koinInject()
val viewState by viewModel.state.collectAsState()
val initialMonsterIndex = viewModel.initialMonsterListPositionIndex

AppScreen(
isOpen = viewState.showDetail,
Expand All @@ -62,7 +63,7 @@ fun MonsterDetailFeature(
) {
MonsterDetailScreen(
viewState.monsters,
viewState.initialMonsterListPositionIndex,
initialMonsterIndex,
contentPadding,
onMonsterChanged = { monster ->
viewModel.onMonsterChanged(monster.index)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
Expand Down Expand Up @@ -96,10 +97,12 @@ internal fun MonsterDetailScreen(
monsters: List<MonsterState>,
initialMonsterIndex: Int,
contentPadding: PaddingValues = PaddingValues(0.dp),
pagerState: PagerState = rememberPagerState(
initialPage = initialMonsterIndex,
pageCount = { monsters.size }
),
pagerState: PagerState = key(monsters) {
rememberPagerState(
initialPage = initialMonsterIndex,
pageCount = { monsters.size }
)
},
scrollState: LazyListState = rememberLazyListState(),
onMonsterChanged: (monster: MonsterState) -> Unit = {},
onOptionsClicked: () -> Unit = {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package br.alexandregpereira.hunter.monster.detail

import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.ADD_TO_FOLDER
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CHANGE_TO_FEET
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CHANGE_TO_METERS
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CLONE
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.DELETE
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.EDIT
Expand Down Expand Up @@ -80,22 +78,6 @@ data class MonsterDetailOptionState(
name = strings.delete
)
}

@Suppress("FunctionName")
internal fun ChangeToFeet(strings: MonsterDetailStrings): MonsterDetailOptionState {
return MonsterDetailOptionState(
id = CHANGE_TO_FEET,
name = strings.optionsChangeToFeet
)
}

@Suppress("FunctionName")
internal fun ChangeToMeters(strings: MonsterDetailStrings): MonsterDetailOptionState {
return MonsterDetailOptionState(
id = CHANGE_TO_METERS,
name = strings.optionsChangeToMeters
)
}
}
}

Expand All @@ -104,8 +86,6 @@ enum class MonsterDetailOptionStateId {
CLONE,
EDIT,
DELETE,
CHANGE_TO_FEET,
CHANGE_TO_METERS,
RESET_TO_ORIGINAL,
EXPORT,
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import kotlin.native.ObjCName
@ObjCName(name = "MonsterDetailState", exact = true)
data class MonsterDetailState(
val isLoading: Boolean = true,
val initialMonsterListPositionIndex: Int = 0,
val monsters: List<MonsterState> = emptyList(),
val showOptions: Boolean = false,
val options: List<MonsterDetailOptionState> = emptyList(),
Expand Down Expand Up @@ -195,12 +194,10 @@ val MonsterDetailState.HideOptions: MonsterDetailState
get() = this.copy(showOptions = false)

fun MonsterDetailState.complete(
initialMonsterListPositionIndex: Int,
monsters: List<MonsterState>,
options: List<MonsterDetailOptionState>
): MonsterDetailState = this.copy(
isLoading = false,
initialMonsterListPositionIndex = initialMonsterListPositionIndex,
monsters = monsters,
options = options
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,8 @@ package br.alexandregpereira.hunter.monster.detail

import br.alexadregpereira.hunter.shareContent.event.ShareContentEvent
import br.alexadregpereira.hunter.shareContent.event.ShareContentEventDispatcher
import br.alexandregpereira.hunter.domain.model.MeasurementUnit
import br.alexandregpereira.hunter.domain.model.Monster
import br.alexandregpereira.hunter.domain.model.MonsterStatus
import br.alexandregpereira.hunter.domain.usecase.ChangeMonstersMeasurementUnitUseCase
import br.alexandregpereira.hunter.event.EventDispatcher
import br.alexandregpereira.hunter.event.EventListener
import br.alexandregpereira.hunter.event.folder.insert.FolderInsertEvent
Expand All @@ -36,8 +34,6 @@ import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionState.Compa
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionState.Companion.Export
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionState.Companion.ResetToOriginal
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.ADD_TO_FOLDER
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CHANGE_TO_FEET
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CHANGE_TO_METERS
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.CLONE
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.DELETE
import br.alexandregpereira.hunter.monster.detail.MonsterDetailOptionStateId.EDIT
Expand All @@ -64,24 +60,24 @@ import br.alexandregpereira.hunter.state.UiModel
import br.alexandregpereira.hunter.sync.event.SyncEventDispatcher
import br.alexandregpereira.hunter.ui.StateRecovery
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.cancellable
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.withContext

class MonsterDetailStateHolder internal constructor(
private val getMonsterDetailUseCase: GetMonsterDetailUseCase,
private val cloneMonster: CloneMonsterUseCase,
private val changeMonstersMeasurementUnitUseCase: ChangeMonstersMeasurementUnitUseCase,
private val deleteMonster: DeleteMonsterUseCase,
private val resetMonsterToOriginal: ResetMonsterToOriginal,
private val spellDetailEventDispatcher: SpellDetailEventDispatcher,
Expand All @@ -107,6 +103,8 @@ class MonsterDetailStateHolder internal constructor(
private var currentJob: Job? = null
private var enableMonsterPageChangesEventDispatch = false
private var metadata: List<Monster> = emptyList()
var initialMonsterListPositionIndex: Int = 0
private set

init {
setState { updateState(stateRecovery) }
Expand Down Expand Up @@ -155,17 +153,37 @@ class MonsterDetailStateHolder internal constructor(
monsterIndexes: List<String>,
invalidateCache: Boolean = false
) {
if (state.value.showDetail.not()) return

stateRecovery.saveMonsterIndexes(monsterIndexes)
onMonsterChanged(monsterIndex, scrolled = false)
getMonsterDetail(invalidateCache = invalidateCache).collectDetail()
currentJob?.cancel()
currentJob = getMonsterDetail(invalidateCache = invalidateCache)
.cancellable()
.toMonsterDetailState()
.flowOn(dispatcher)
.onStart {
setState { copy(isLoading = true) }
}
.catch {
setState { copy(isLoading = false) }
it.printStackTrace()
analytics.logException(it)
}
.emitState()
.onEach { state ->
analytics.trackMonsterDetailLoaded(monsterIndex, state.monsters)
}
.launchIn(scope)
}

fun onMonsterChanged(monsterIndex: String, scrolled: Boolean = true) {
if (enableMonsterPageChangesEventDispatch && scrolled && monsterIndex != this.monsterIndex) {
analytics.trackMonsterPageChanged(monsterIndex, scrolled)
monsterEventDispatcher.dispatchEvent(OnMonsterPageChanges(monsterIndex))
if (scrolled && monsterIndex != this.monsterIndex) {
initialMonsterListPositionIndex = state.value.monsters.indexOfFirst {
it.index == monsterIndex
}
if (enableMonsterPageChangesEventDispatch) {
analytics.trackMonsterPageChanged(monsterIndex, scrolled)
monsterEventDispatcher.dispatchEvent(OnMonsterPageChanges(monsterIndex))
}
}
stateRecovery.saveMonsterIndex(monsterIndex)
setState { changeOptions() }
Expand Down Expand Up @@ -209,14 +227,6 @@ class MonsterDetailStateHolder internal constructor(
setState { copy(showResetConfirmation = true) }
}

CHANGE_TO_FEET -> {
changeMeasurementUnit(MeasurementUnit.FEET)
}

CHANGE_TO_METERS -> {
changeMeasurementUnit(MeasurementUnit.METER)
}

EXPORT -> {
analytics.trackMonsterDetailExportClicked(monsterIndex)
shareContentEventDispatcher.dispatchEvent(
Expand Down Expand Up @@ -288,41 +298,17 @@ class MonsterDetailStateHolder internal constructor(
)
}

@OptIn(ExperimentalCoroutinesApi::class)
private fun changeMeasurementUnit(measurementUnit: MeasurementUnit) {
changeMonstersMeasurementUnitUseCase(monsterIndex, measurementUnit)
.flatMapLatest { getMonsterDetail() }
.collectDetail()
}

private fun Flow<MonsterDetail>.collectDetail() {
currentJob?.cancel()
currentJob = this.cancellable()
.toMonsterDetailState()
.flowOn(dispatcher)
.onStart {
setState { copy(isLoading = true) }
}
.catch {
setState { copy(isLoading = false) }
it.printStackTrace()
analytics.logException(it)
}
.emitState()
.onEach { state ->
analytics.trackMonsterDetailLoaded(monsterIndex, state.monsters)
}
.launchIn(scope)
}

private fun Flow<MonsterDetail>.toMonsterDetailState(): Flow<MonsterDetailState> {
return map {
metadata = it.monsters
val strings = appLocalization.getStrings()
withContext(Dispatchers.Main) {
metadata = it.monsters
initialMonsterListPositionIndex = it.monsterIndexSelected
}
MonsterDetailState(
initialMonsterListPositionIndex = it.monsterIndexSelected,
monsters = it.monsters.asState(strings),
measurementUnit = it.measurementUnit,
strings = strings,
).changeOptions()
}
}
Expand All @@ -331,7 +317,6 @@ class MonsterDetailStateHolder internal constructor(
return onEach { state ->
setState {
complete(
initialMonsterListPositionIndex = state.initialMonsterListPositionIndex,
monsters = state.monsters,
options = state.options
).saveState(stateRecovery)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ interface MonsterDetailStrings {
val innateSpellcasting: String
val abilityScores: String
val optionsAddToFolder: String
val optionsChangeToFeet: String
val optionsChangeToMeters: String
val savingThrowStrength: String
val savingThrowDexterity: String
val savingThrowConstitution: String
Expand Down Expand Up @@ -74,8 +72,6 @@ internal data class MonsterDetailEnStrings(
override val innateSpellcasting: String = "Innate Spellcasting",
override val abilityScores: String = "Ability Scores",
override val optionsAddToFolder: String = "Add to Folder",
override val optionsChangeToFeet: String = "Change to Feet",
override val optionsChangeToMeters: String = "Change to Meters",
override val savingThrowStrength: String = "Strength",
override val savingThrowDexterity: String = "Dexterity",
override val savingThrowConstitution: String = "Constitution",
Expand Down Expand Up @@ -119,8 +115,6 @@ internal data class MonsterDetailPtStrings(
override val innateSpellcasting: String = "Conjuração Inata",
override val abilityScores: String = "Atributos",
override val optionsAddToFolder: String = "Adicionar à Pasta",
override val optionsChangeToFeet: String = "Mudar para Pés",
override val optionsChangeToMeters: String = "Mudar para Metros",
override val savingThrowStrength: String = "Força",
override val savingThrowDexterity: String = "Destreza",
override val savingThrowConstitution: String = "Constituição",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ val monsterDetailModule = module {
MonsterDetailStateHolder(
getMonsterDetailUseCase = get(),
cloneMonster = get(),
changeMonstersMeasurementUnitUseCase = get(),
deleteMonster = get(),
spellDetailEventDispatcher = get(),
monsterEventDispatcher = get(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ val spellCompendiumModule = module {

factory { GetSpellsUseCase(repository = get()) }

factory {
single {
SpellCompendiumStateHolder(
dispatcher = Dispatchers.Default,
getSpellsUseCase = get(),
Expand Down

0 comments on commit 4357ab3

Please sign in to comment.