Add favorite skill edit.

This commit is contained in:
Thomas Andres Gomez 2023-12-13 09:27:51 +01:00
parent d256ba70ac
commit 6fb3b2c10c
6 changed files with 78 additions and 44 deletions

View file

@ -65,6 +65,7 @@ import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.composable.KeepOnScreen import com.pixelized.rplexicon.ui.composable.KeepOnScreen
import com.pixelized.rplexicon.ui.composable.Loader import com.pixelized.rplexicon.ui.composable.Loader
import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog
import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog
import com.pixelized.rplexicon.ui.composable.error.HandleFetchError import com.pixelized.rplexicon.ui.composable.error.HandleFetchError
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSearch import com.pixelized.rplexicon.ui.navigation.screens.navigateToSearch
@ -74,6 +75,7 @@ import com.pixelized.rplexicon.ui.screens.character.CharacterTabUio.Inventory
import com.pixelized.rplexicon.ui.screens.character.CharacterTabUio.Proficiency import com.pixelized.rplexicon.ui.screens.character.CharacterTabUio.Proficiency
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeader import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeader
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.character.ResourcePointUio
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterHeaderStatePreview import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterHeaderStatePreview
import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPage import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPage
import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPagePreview import com.pixelized.rplexicon.ui.screens.character.pages.actions.ActionPagePreview
@ -156,7 +158,7 @@ fun CharacterSheetScreen(
}, },
onHitPoint = headerViewModel::toggleHitPointDialog, onHitPoint = headerViewModel::toggleHitPointDialog,
onResource = { onResource = {
// TODO() headerViewModel.showSkillEditDialog(item = it)
}, },
onDeathRoll = { onDeathRoll = {
overlay.prepareRoll(diceThrow = headerViewModel.onDeathThrow()) overlay.prepareRoll(diceThrow = headerViewModel.onDeathThrow())
@ -226,6 +228,12 @@ fun CharacterSheetScreen(
onConfirm = headerViewModel::applyHitPointChange, onConfirm = headerViewModel::applyHitPointChange,
) )
HandleSkillEditDialog(
dialog = headerViewModel.skillEditDialog,
onDismissRequest = headerViewModel::hideSkillEditDialog,
onConfirm = headerViewModel::applySkillChange,
)
HandleFetchError( HandleFetchError(
errors = viewModel.error, errors = viewModel.error,
) )
@ -261,7 +269,7 @@ private fun CharacterSheetContent(
tabs: State<List<CharacterTabUio>>, tabs: State<List<CharacterTabUio>>,
header: State<CharacterSheetHeaderUio?>, header: State<CharacterSheetHeaderUio?>,
onHitPoint: () -> Unit, onHitPoint: () -> Unit,
onResource: () -> Unit, onResource: (ResourcePointUio) -> Unit,
onDeathRoll: () -> Unit, onDeathRoll: () -> Unit,
onDeathSuccess: () -> Unit, onDeathSuccess: () -> Unit,
onDeathFailure: () -> Unit, onDeathFailure: () -> Unit,

View file

@ -37,7 +37,7 @@ fun CharacterSheetHeader(
padding: PaddingValues = PaddingValues(start = 16.dp, end = 16.dp, bottom = 4.dp), padding: PaddingValues = PaddingValues(start = 16.dp, end = 16.dp, bottom = 4.dp),
header: State<CharacterSheetHeaderUio?>, header: State<CharacterSheetHeaderUio?>,
onHitPoint: () -> Unit, onHitPoint: () -> Unit,
onResource: () -> Unit, onResource: (ResourcePointUio) -> Unit,
onDeathRoll: () -> Unit, onDeathRoll: () -> Unit,
onDeathSuccess: () -> Unit, onDeathSuccess: () -> Unit,
onDeathFailure: () -> Unit, onDeathFailure: () -> Unit,
@ -58,7 +58,7 @@ fun CharacterSheetHeader(
), ),
) { ) {
header.value?.resource?.let { header.value?.resource?.let {
ResourcePoint(label = it, onClick = onResource) ResourcePoint(resource = it, onClick = onResource)
} }
header.value?.armorClass?.let { header.value?.armorClass?.let {
LabelPoint(label = it) LabelPoint(label = it)

View file

@ -26,9 +26,10 @@ import com.pixelized.rplexicon.ui.theme.LexiconTheme
@Stable @Stable
data class ResourcePointUio( data class ResourcePointUio(
val label: Int?, val id: String,
val value: String?, val label: Int,
val max: String? = null, val value: Int,
val max: Int,
) )
@Composable @Composable
@ -37,26 +38,24 @@ fun ResourcePoint(
labelStyle: TextStyle = MaterialTheme.typography.labelSmall, labelStyle: TextStyle = MaterialTheme.typography.labelSmall,
valueStyle: TextStyle = MaterialTheme.typography.headlineSmall, valueStyle: TextStyle = MaterialTheme.typography.headlineSmall,
maxStyle: TextStyle = MaterialTheme.typography.titleSmall, maxStyle: TextStyle = MaterialTheme.typography.titleSmall,
label: ResourcePointUio, resource: ResourcePointUio,
onClick: (() -> Unit)? = null, onClick: (ResourcePointUio) -> Unit,
) { ) {
Column( Column(
modifier = Modifier modifier = Modifier
.clickable( .clickable(
interactionSource = remember { MutableInteractionSource() }, interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false), indication = rememberRipple(bounded = false),
enabled = onClick != null, onClick = { onClick?.invoke() } onClick = { onClick(resource) }
) )
.then(other = modifier), .then(other = modifier),
horizontalAlignment = Alignment.CenterHorizontally horizontalAlignment = Alignment.CenterHorizontally
) { ) {
label.label?.let {
Text( Text(
style = labelStyle, style = labelStyle,
fontWeight = FontWeight.Light, fontWeight = FontWeight.Light,
text = stringResource(id = it), text = stringResource(id = resource.label),
) )
}
Row( Row(
horizontalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp),
) { ) {
@ -68,18 +67,16 @@ fun ResourcePoint(
else -> MaterialTheme.colorScheme.primary else -> MaterialTheme.colorScheme.primary
}, },
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
text = label.value ?: "0" text = "${resource.value}"
) )
label.max?.let {
Text( Text(
modifier = Modifier.alignByBaseline(), modifier = Modifier.alignByBaseline(),
style = maxStyle, style = maxStyle,
text = it, text = "/ ${resource.max}",
) )
} }
} }
} }
}
@Composable @Composable
@Preview(uiMode = UI_MODE_NIGHT_NO) @Preview(uiMode = UI_MODE_NIGHT_NO)
@ -88,10 +85,11 @@ private fun LabelPointPreview() {
LexiconTheme { LexiconTheme {
Surface { Surface {
ResourcePoint( ResourcePoint(
label = ResourcePointUio( resource = ResourcePointUio(
id = "Inspiration Bardique",
label = R.string.character_sheet_title_inspiration, label = R.string.character_sheet_title_inspiration,
value = "2", value = 2,
max = "/ 2", max = 2,
), ),
onClick = { }, onClick = { },
) )

View file

@ -36,9 +36,10 @@ fun rememberCharacterHeaderStatePreview(
value = "13", value = "13",
), ),
resource = ResourcePointUio( resource = ResourcePointUio(
id = "Rage",
label = R.string.character_sheet_title_rage, label = R.string.character_sheet_title_rage,
value = "2", value = 2,
max = "/ 2", max = 2,
), ),
death = death, death = death,
) )

View file

@ -1,6 +1,7 @@
package com.pixelized.rplexicon.ui.screens.character.factory package com.pixelized.rplexicon.ui.screens.character.factory
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.character.DeathThrowUio import com.pixelized.rplexicon.ui.screens.character.composable.character.DeathThrowUio
import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio import com.pixelized.rplexicon.ui.screens.character.composable.character.LabelPointUio
@ -8,12 +9,19 @@ import com.pixelized.rplexicon.ui.screens.character.composable.character.Resourc
import com.pixelized.rplexicon.ui.screens.character.pages.actions.HeaderViewModel import com.pixelized.rplexicon.ui.screens.character.pages.actions.HeaderViewModel
import javax.inject.Inject import javax.inject.Inject
class CharacterSheetHeaderUioFactory @Inject constructor() { class CharacterSheetHeaderUioFactory @Inject constructor(
private val skillRepository: SkillRepository,
) {
fun convert( fun convert(
character: String,
sheetHeaderData: HeaderViewModel.SheetHeaderData?, sheetHeaderData: HeaderViewModel.SheetHeaderData?,
fireHeaderData: HeaderViewModel.FireHeaderData?, fireHeaderData: HeaderViewModel.FireHeaderData?,
): CharacterSheetHeaderUio { ): CharacterSheetHeaderUio {
val characterClass = sheetHeaderData?.characterClass
val favoriteSkill = skillRepository.find(
character = character,
skill = sheetHeaderData?.characterClass?.resource
)
return CharacterSheetHeaderUio( return CharacterSheetHeaderUio(
armorClass = LabelPointUio( armorClass = LabelPointUio(
label = R.string.character_sheet_title_ca, label = R.string.character_sheet_title_ca,
@ -36,11 +44,12 @@ class CharacterSheetHeaderUioFactory @Inject constructor() {
value = "$it", value = "$it",
) )
}, },
resource = if (sheetHeaderData?.resourceMax != null) { resource = if (characterClass?.label != null && favoriteSkill?.amount != null) {
ResourcePointUio( ResourcePointUio(
label = sheetHeaderData.resourceLabel, id = favoriteSkill.name,
value = "${fireHeaderData?.resource ?: 0}", label = characterClass.label,
max = "/ ${sheetHeaderData.resourceMax}" value = fireHeaderData?.resource ?: 0,
max = favoriteSkill.amount,
) )
} else { } else {
null null

View file

@ -7,6 +7,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.pixelized.rplexicon.data.model.CharacterSheet
import com.pixelized.rplexicon.data.model.DiceThrow import com.pixelized.rplexicon.data.model.DiceThrow
import com.pixelized.rplexicon.data.model.Property import com.pixelized.rplexicon.data.model.Property
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
@ -14,8 +15,10 @@ import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.SkillRepository import com.pixelized.rplexicon.data.repository.character.SkillRepository
import com.pixelized.rplexicon.ui.composable.edit.HpPointDialogUio import com.pixelized.rplexicon.ui.composable.edit.HpPointDialogUio
import com.pixelized.rplexicon.ui.composable.edit.SkillEditDialogUio
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio import com.pixelized.rplexicon.ui.screens.character.composable.character.CharacterSheetHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.character.ResourcePointUio
import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetHeaderUioFactory import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetHeaderUioFactory
import com.pixelized.rplexicon.utilitary.extentions.local.sum import com.pixelized.rplexicon.utilitary.extentions.local.sum
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
@ -41,6 +44,7 @@ class HeaderViewModel @Inject constructor(
val header: State<CharacterSheetHeaderUio?> = derivedStateOf { val header: State<CharacterSheetHeaderUio?> = derivedStateOf {
headerFactory.convert( headerFactory.convert(
character = character,
sheetHeaderData = sheetData.value, sheetHeaderData = sheetData.value,
fireHeaderData = fireData.value, fireHeaderData = fireData.value,
) )
@ -49,6 +53,9 @@ class HeaderViewModel @Inject constructor(
private val _hitPointDialog = mutableStateOf<HpPointDialogUio?>(null) private val _hitPointDialog = mutableStateOf<HpPointDialogUio?>(null)
val hitPointDialog: State<HpPointDialogUio?> get() = _hitPointDialog val hitPointDialog: State<HpPointDialogUio?> get() = _hitPointDialog
private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null)
val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog
init { init {
viewModelScope.launch { viewModelScope.launch {
launch(context = Dispatchers.IO) { launch(context = Dispatchers.IO) {
@ -60,14 +67,9 @@ class HeaderViewModel @Inject constructor(
val alterations = alterationRepository.getActiveAlterationsStatus( val alterations = alterationRepository.getActiveAlterationsStatus(
character = sheet.name, character = sheet.name,
) )
val resource = sheet.characterClass.firstOrNull()
val data = SheetHeaderData( val data = SheetHeaderData(
hpMax = sheet.hitPoint + alterations[Property.HIT_POINT].sum, hpMax = sheet.hitPoint + alterations[Property.HIT_POINT].sum,
resourceLabel = resource?.label, characterClass = sheet.characterClass.firstOrNull(),
resourceMax = skillRepository.find(
character = character,
skill = resource?.resource,
)?.amount,
speed = sheet.speed, speed = sheet.speed,
ca = sheet.armorClass + alterations[Property.ARMOR_CLASS].sum, ca = sheet.armorClass + alterations[Property.ARMOR_CLASS].sum,
dc = sheet.dC, dc = sheet.dC,
@ -150,11 +152,27 @@ class HeaderViewModel @Inject constructor(
_hitPointDialog.value = null _hitPointDialog.value = null
} }
fun showSkillEditDialog(item: ResourcePointUio) {
_skillEditDialog.value = SkillEditDialogUio(
label = item.id,
value = item.value,
max = item.max,
)
}
fun hideSkillEditDialog() {
_skillEditDialog.value = null
}
fun applySkillChange(id: String, value: Int) {
firebaseRepository.setSkill(character = character, name = id, value = value)
hideSkillEditDialog()
}
@Stable @Stable
data class SheetHeaderData( data class SheetHeaderData(
val hpMax: Int, val hpMax: Int,
val resourceLabel: Int?, val characterClass: CharacterSheet.Class?,
val resourceMax: Int?,
val speed: Int, val speed: Int,
val ca: Int, val ca: Int,
val dc: Int?, val dc: Int?,