Add alteration page in the character sheet screen.

This commit is contained in:
Thomas Andres Gomez 2023-10-02 15:46:23 +02:00
parent be602d5325
commit e2209bf005
19 changed files with 398 additions and 69 deletions

View file

@ -2,7 +2,8 @@ package com.pixelized.rplexicon.model
data class Alteration(
val name: String,
val target: String?,
val source: String,
val target: String,
val active: Boolean = false,
val description: String,
val status: Map<Property, Status>,

View file

@ -7,8 +7,9 @@ import com.pixelized.rplexicon.repository.GoogleSheetServiceRepository
import com.pixelized.rplexicon.repository.parser.alteration.AlterationParser
import com.pixelized.rplexicon.utilitary.Update
import com.pixelized.rplexicon.utilitary.exceptions.IncompatibleSheetStructure
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import javax.inject.Inject
import javax.inject.Singleton
@ -17,13 +18,15 @@ class AlterationRepository @Inject constructor(
private val googleRepository: GoogleSheetServiceRepository,
private val alterationParser: AlterationParser,
) {
private val _status = MutableStateFlow<Map<String, Boolean>>(emptyMap())
private val _assignedAlterations = MutableStateFlow<Map<String, List<Alteration>>>(emptyMap())
val assignedAlterations: StateFlow<Map<String, List<Alteration>>> get() = _assignedAlterations
val assignedAlterations: Flow<Map<String, List<Alteration>>> =
combine(_assignedAlterations, _status) { alt, _ -> alt }
var lastSuccessFullUpdate: Update = Update.INITIAL
private set
fun getAlterations(character: String) : List<Alteration> {
fun getAlterations(character: String): List<Alteration> {
return _assignedAlterations.value[character] ?: emptyList()
}
@ -33,6 +36,20 @@ class AlterationRepository @Inject constructor(
}
}
fun getStatus(character: String, alteration: String): Boolean {
return _status.value[character + alteration]
?: _assignedAlterations.value[character]?.firstOrNull { it.name == alteration }?.active
?: false
}
suspend fun setStatus(character: String, alteration: String, value: Boolean?) {
_status.emit(if (value != null) {
_status.value.toMutableMap().also { it[character + alteration] = value }
} else {
_status.value.toMutableMap().also { it.remove(character + alteration) }
})
}
@Throws(IncompatibleSheetStructure::class, Exception::class)
suspend fun fetchAlterationSheet(sheets: List<CharacterSheet>) {
googleRepository.fetch { sheet ->

View file

@ -37,14 +37,16 @@ class AlterationParser @Inject constructor(
row is List<*> -> {
// Assume that the name is the first column.
val alteration = (row.getOrNull(0) as? String)?.let { name ->
val target = row.parseString(TARGET)
val description = row.parseString(DESCRIPTION)
val name = row.getOrNull(0) as? String
val source = row.parseString(SOURCE)
val target = row.parseString(TARGET)
val alteration = if (name != null && source != null && target != null) {
Alteration(
name = name,
source = source,
target = target,
active = false,
description = description ?: "",
description = row.parseString(DESCRIPTION) ?: "",
status = properties
.mapNotNull { property ->
val column = alterationStructure.getValue(property.key)
@ -57,14 +59,15 @@ class AlterationParser @Inject constructor(
}
.toMap(),
)
} else {
null
}
if (alteration != null) {
sheets
.filter { // check if the alteration is applicable to the character
alteration.target?.let { target ->
alteration.target.let { target ->
target == ALL || target == it.characterClass || target == it.race || target == it.name
} ?: false
}
}
.forEach { // check the default alteration state for that character
val column = charactersStructure.getValue(it.name)
@ -124,8 +127,9 @@ class AlterationParser @Inject constructor(
private const val FAIL = "fail"
private const val TARGET = "Cible"
private const val SOURCE = "Source"
private const val DESCRIPTION = "Description"
private val COLUMNS
get() = listOf(TARGET, DESCRIPTION) + Property.values().map { it.key }
get() = listOf(SOURCE, TARGET, DESCRIPTION) + Property.values().map { it.key }
}
}

View file

@ -59,6 +59,9 @@ 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.AttackActionViewModel
import com.pixelized.rplexicon.ui.screens.character.pages.actions.SpellsActionViewModel
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPage
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPagePreview
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationViewModel
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellLevelChooser
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellLevelChooserPreview
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPage
@ -77,6 +80,7 @@ fun CharacterSheetScreen(
proficiencyViewModel: ProficiencyViewModel = hiltViewModel(),
attackViewModel: AttackActionViewModel = hiltViewModel(),
spellsViewModel: SpellsActionViewModel = hiltViewModel(),
alterationsViewModel: AlterationViewModel = hiltViewModel(),
) {
val screen = LocalScreenNavHost.current
val overlay = LocalRollOverlay.current
@ -93,7 +97,8 @@ fun CharacterSheetScreen(
val haveSheet = proficiencyViewModel.sheet.value != null
val haveAction = attackViewModel.attacks.value.isNotEmpty()
val haveSpell = spellsViewModel.spells.value.isNotEmpty()
(if (haveSheet) 1 else 0) + (if (haveAction || haveSpell) 1 else 0)
val haveAlteration = alterationsViewModel.alterations.value.isNotEmpty()
haveSheet.toInt() + (haveAction || haveSpell).toInt() + haveAlteration.toInt()
}
Surface(
modifier = Modifier.fillMaxSize(),
@ -136,6 +141,11 @@ fun CharacterSheetScreen(
spellsViewModel = spellsViewModel,
)
},
alterations = {
AlterationPage(
viewModel = alterationsViewModel,
)
},
sheet = {
SpellLevelChooser(
modifier = Modifier.navigationBarsPadding(),
@ -176,6 +186,7 @@ private fun CharacterSheetContent(
loader: @Composable BoxScope.() -> Unit,
proficiencies: @Composable PagerScope.() -> Unit,
actions: @Composable PagerScope.() -> Unit,
alterations: @Composable PagerScope.() -> Unit,
sheet: @Composable () -> Unit,
) {
Scaffold(
@ -234,12 +245,13 @@ private fun CharacterSheetContent(
.fillMaxWidth()
.pullRefresh(refreshState),
state = pagerState,
beyondBoundsPageCount = 1,
beyondBoundsPageCount = 2,
verticalAlignment = Alignment.Top,
pageContent = { page ->
when (page) {
0 -> proficiencies()
1 -> actions()
2 -> alterations()
}
}
)
@ -264,7 +276,7 @@ private fun CharacterScreenPreview(
LexiconTheme {
Surface {
val sheetState = rememberModalBottomSheetState(
initialValue = when (preview == 2) {
initialValue = when (preview == 3) {
true -> ModalBottomSheetValue.Expanded
else -> ModalBottomSheetValue.Hidden
},
@ -280,12 +292,15 @@ private fun CharacterScreenPreview(
loader = { },
proficiencies = { ProficiencyPreview() },
actions = { ActionPagePreview() },
alterations = { AlterationPagePreview() },
sheet = { SpellLevelChooserPreview() },
)
}
}
}
private fun Boolean.toInt(): Int = if (this) 1 else 0
private class CharacterScreenPreviewProvider : PreviewParameterProvider<Int> {
override val values: Sequence<Int> = sequenceOf(0, 1, 2)
override val values: Sequence<Int> = sequenceOf(0, 1, 2, 3)
}

View file

@ -4,13 +4,11 @@ import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.annotation.DrawableRes
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface

View file

@ -1,7 +1,8 @@
package com.pixelized.rplexicon.ui.screens.character.composable.actions
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.annotation.DrawableRes
import androidx.compose.foundation.Indication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Column
@ -9,14 +10,18 @@ import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.theme.LexiconTheme
@Composable
fun DiceButton(
@ -46,4 +51,19 @@ fun DiceButton(
text = text,
)
}
}
@Composable
@Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES)
private fun DiceButtonPreview() {
LexiconTheme {
Surface {
DiceButton(
icon = R.drawable.ic_d20_24,
text = "1d20",
onClick = { },
)
}
}
}

View file

@ -19,6 +19,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
@ -93,11 +94,13 @@ fun SpellHeader(
count.max?.let { max ->
Text(
modifier = Modifier.alignByBaseline(),
fontWeight = FontWeight.Light,
style = MaterialTheme.typography.labelSmall,
text = "/",
)
Text(
modifier = Modifier.alignByBaseline(),
fontWeight = FontWeight.Light,
style = MaterialTheme.typography.bodySmall,
text = "$max",
)

View file

@ -12,7 +12,6 @@ import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.sizeIn
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
@ -95,6 +94,7 @@ fun Spell(
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic,
overflow = TextOverflow.Ellipsis,
maxLines = 1,

View file

@ -0,0 +1,106 @@
package com.pixelized.rplexicon.ui.screens.character.pages.alteration
import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Surface
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.rplexicon.ui.screens.rolls.composable.AlterationDetail
import com.pixelized.rplexicon.ui.screens.rolls.composable.AlterationDetailUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlteration
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import kotlinx.coroutines.launch
@Composable
fun AlterationPage(
viewModel: AlterationViewModel = hiltViewModel(),
) {
val scope = rememberCoroutineScope()
AlterationPageContent(
alterations = viewModel.alterations,
onInfo = {
viewModel.showAlterationDetail(id = it)
},
onClick = {
scope.launch {
viewModel.toggle(alteration = it)
}
},
)
AlterationDetailHandler(
detail = viewModel.alterationDetail,
onDismissRequest = { viewModel.hideAlterationDetail() },
)
}
@Composable
fun AlterationPageContent(
modifier: Modifier = Modifier,
alterations: State<List<RollAlterationUio>>,
onInfo: (String) -> Unit,
onClick: (String) -> Unit,
) {
LazyColumn(
modifier = modifier,
contentPadding = PaddingValues(vertical = 8.dp),
) {
items(items = alterations.value) {
RollAlteration(
modifier = Modifier.fillMaxWidth(),
alteration = it,
onInfo = onInfo,
onClick = onClick,
)
}
}
}
@Composable
private fun AlterationDetailHandler(
detail: State<AlterationDetailUio?>,
onDismissRequest: () -> Unit,
) {
detail.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
AlterationDetail(
detail = it,
onClose = onDismissRequest,
)
}
}
}
@Composable
@Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES)
fun AlterationPagePreview() {
LexiconTheme {
Surface {
AlterationPageContent(
alterations = rememberRollAlterations(),
onInfo = { },
onClick = { },
)
}
}
}

View file

@ -0,0 +1,66 @@
package com.pixelized.rplexicon.ui.screens.character.pages.alteration
import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.rplexicon.repository.data.AlterationRepository
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.rolls.composable.AlterationDetailUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio
import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import javax.inject.Inject
@HiltViewModel
class AlterationViewModel @Inject constructor(
private val repository: AlterationRepository,
private val factory: AlterationFactory,
savedStateHandle: SavedStateHandle,
) : ViewModel() {
private val character = savedStateHandle.characterSheetArgument.name
private val _alterations = mutableStateOf<List<RollAlterationUio>>(emptyList())
val alterations: State<List<RollAlterationUio>> get() = _alterations
private val _alterationDetail = mutableStateOf<AlterationDetailUio?>(null)
val alterationDetail: State<AlterationDetailUio?> get() = _alterationDetail
init {
viewModelScope.launch {
repository.assignedAlterations.collect {
_alterations.value = withContext(Dispatchers.IO) {
val alterations = it[character] ?: emptyList()
factory.convert(character = character, alterations = alterations)
.sortedBy { it.label }
.sortedBy { it.subLabel }
}
}
}
}
suspend fun toggle(alteration: String) {
val value = repository.getStatus(character = character, alteration = alteration)
repository.setStatus(character = character, alteration = alteration, value.not())
}
fun showAlterationDetail(id: String) {
val alteration = repository.getAlterations(character = character).firstOrNull { it.name == id }
if (alteration != null) {
_alterationDetail.value = AlterationDetailUio(
name = id,
source = alteration.source,
target = alteration.target,
description = alteration.description
)
}
}
fun hideAlterationDetail() {
_alterationDetail.value = null
}
}

View file

@ -76,6 +76,7 @@ import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDice
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import kotlinx.coroutines.launch
@ -315,20 +316,8 @@ private fun RollOverlayPreview(
drawer = rememberDrawerState(initialValue = preview.drawer),
dice = preview.dice,
card = preview.card,
alterations = remember {
mutableStateOf(
listOf(
RollAlterationUio(
label = "Critique",
haveDescription = true,
checked = true
),
)
)
},
showDetail = remember {
mutableStateOf(true)
},
alterations = rememberRollAlterations(),
showDetail = remember { mutableStateOf(true) },
onMenu = { },
onMenuClose = { },
onClose = { },

View file

@ -52,6 +52,8 @@ class RollOverlayViewModel @Inject constructor(
_card.value = null
_dice.value = diceFactory.convertDiceThrow(diceThrow)
_alterations.value = alterationFactory.convertDiceThrow(diceThrow)
.sortedBy { it.label }
.sortedBy { it.subLabel }
}
fun onAlteration(id: String) {
@ -99,6 +101,8 @@ class RollOverlayViewModel @Inject constructor(
if (alteration != null) {
_alterationDetail.value = AlterationDetailUio(
name = id,
source = alteration.source,
target = alteration.target,
description = alteration.description
)
}

View file

@ -22,16 +22,21 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.lexicon
@Stable
data class AlterationDetailUio(
val name: String,
val source: String,
val target: String,
val description: String,
)
@ -49,7 +54,9 @@ fun AlterationDetail(
) {
Column {
Row(
modifier = Modifier.fillMaxWidth().padding(start = 24.dp),
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top,
) {
@ -76,15 +83,29 @@ fun AlterationDetail(
)
}
}
Text(
Column(
modifier = Modifier
.padding(top = 8.dp)
.verticalScroll(rememberScrollState())
.padding(horizontal = 24.dp)
.padding(top = 8.dp, bottom = 24.dp),
style = MaterialTheme.typography.bodyMedium,
text = detail.description,
)
.padding(horizontal = 24.dp),
) {
Text(
fontWeight = FontWeight.Light,
style = MaterialTheme.typography.labelSmall,
text = stringResource(id = R.string.alteration_source, detail.source),
)
Text(
fontWeight = FontWeight.Light,
style = MaterialTheme.typography.labelSmall,
text = stringResource(id = R.string.alteration_target, detail.target),
)
Text(
modifier = Modifier.padding(top = 8.dp, bottom = 24.dp),
style = MaterialTheme.typography.bodyMedium,
text = detail.description,
)
}
}
}
}
@ -97,6 +118,8 @@ private fun AlterationDetailPreview() {
AlterationDetail(
detail = AlterationDetailUio(
name = "Rage",
source = "Barbare",
target = "Barbare",
description = "\"En combat, vous vous battez avec une férocité bestiale. Durant votre tour, vous pouvez entrer en rage en utilisant une action bonus. En rage, vous gagnez les bénéfices suivants si vous ne portez pas d'armure lourde :\n" +
"\n" +
"Vous avez un avantage aux jets de Force et aux jets de sauvegarde de Force.\n" +

View file

@ -4,8 +4,10 @@ import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Info
@ -19,6 +21,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
@ -28,8 +31,8 @@ import com.pixelized.rplexicon.ui.theme.LexiconTheme
@Stable
data class RollAlterationUio(
val label: String,
val subLabel: String?,
val checked: Boolean,
val haveDescription: Boolean,
)
@Composable
@ -40,25 +43,37 @@ fun RollAlteration(
onClick: (id: String) -> Unit,
) {
Row(
modifier = modifier
modifier = Modifier
.clickable { onClick(alteration.label) }
.padding(horizontal = 16.dp),
.heightIn(min = 52.dp)
.padding(horizontal = 16.dp)
.then(other = modifier),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween,
) {
Text(
style = MaterialTheme.typography.bodyMedium,
text = alteration.label,
)
Column(
verticalArrangement = Arrangement.spacedBy(space = 2.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = alteration.label,
)
alteration.subLabel?.let {
Text(
style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Light,
text = it,
)
}
}
Row {
if (alteration.haveDescription) {
IconButton(onClick = { onInfo(alteration.label) }) {
Icon(
imageVector = Icons.Outlined.Info,
contentDescription = null,
)
}
IconButton(onClick = { onInfo(alteration.label) }) {
Icon(
imageVector = Icons.Outlined.Info,
contentDescription = null,
)
}
Switch(
enabled = true,
@ -89,8 +104,20 @@ private fun RollAlterationPreview(
private class RollAlterationPreviewProvider : PreviewParameterProvider<RollAlterationUio> {
override val values: Sequence<RollAlterationUio> = sequenceOf(
RollAlterationUio(label = "Critique", checked = false, haveDescription = false),
RollAlterationUio(label = "Rage", checked = true, haveDescription = true),
RollAlterationUio(label = "Bénédiction", checked = false, haveDescription = false),
RollAlterationUio(
label = "Critique",
checked = false,
subLabel = null,
),
RollAlterationUio(
label = "Rage",
checked = true,
subLabel = "Barbare",
),
RollAlterationUio(
label = "Bénédiction",
checked = false,
subLabel = "Clerc",
),
)
}

View file

@ -1,7 +1,6 @@
package com.pixelized.rplexicon.ui.screens.rolls.factory
import android.app.Application
import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.model.Alteration
import com.pixelized.rplexicon.model.DiceThrow
import com.pixelized.rplexicon.model.Property
import com.pixelized.rplexicon.repository.data.ActionRepository
@ -11,11 +10,20 @@ import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio
import javax.inject.Inject
class AlterationFactory @Inject constructor(
private val application: Application,
private val actionRepository: ActionRepository,
private val spellRepository: SpellRepository,
private val alterationRepository: AlterationRepository,
) {
fun convert(character: String, alterations: List<Alteration>): List<RollAlterationUio> {
return alterations.map {
RollAlterationUio(
label = it.name,
checked = alterationRepository.getStatus(character, it.name),
subLabel = it.source,
)
}
}
fun convertDiceThrow(diceThrow: DiceThrow): List<RollAlterationUio> {
val properties = when (diceThrow) {
is DiceThrow.Initiative -> listOf(Property.INITIATIVE, Property.DEXTERITY)
@ -90,8 +98,8 @@ class AlterationFactory @Inject constructor(
.map {
RollAlterationUio(
label = it.name,
checked = it.active,
haveDescription = true,
checked = alterationRepository.getStatus(diceThrow.character, it.name),
subLabel = it.source,
)
}
}

View file

@ -0,0 +1,36 @@
package com.pixelized.rplexicon.ui.screens.rolls.preview
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollAlterationUio
@Composable
@Stable
fun rememberRollAlterations() = remember {
mutableStateOf(
listOf(
RollAlterationUio(
label = "Rage",
subLabel = "Barbare",
checked = false,
),
RollAlterationUio(
label = "Inspiration bardique",
subLabel = "Barde",
checked = false
),
RollAlterationUio(
label = "Bénédiction",
subLabel = "Clerc",
checked = false,
),
RollAlterationUio(
label = "Cape de protection",
subLabel = "Équipement",
checked = true
),
)
)
}

View file

@ -152,17 +152,23 @@ private fun SpellDetailContent(
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_school),
)
if (detail.ritual) {
Text(
style = MaterialTheme.typography.bodyMedium,
text = stringResource(id = R.string.spell_detail_ritual),
)
}
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.bodyMedium,
text = stringResource(id = detail.school),
)
if (detail.ritual) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.bodyMedium,
text = "-",
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.bodyMedium,
text = stringResource(id = R.string.spell_detail_ritual),
)
}
}
FlowRow(

View file

@ -151,4 +151,7 @@
<string name="spell_detail_description">Description</string>
<string name="spell_level_chooser_label">Sort de niveau %1$s</string>
<string name="spell_level_chooser_available">Disponible : </string>
<string name="alteration_source">Source : %1$s</string>
<string name="alteration_target">Cible : %1$s</string>
</resources>

View file

@ -151,4 +151,7 @@
<string name="spell_detail_description">Description</string>
<string name="spell_level_chooser_label">Spell level %1$s</string>
<string name="spell_level_chooser_available">Available: </string>
<string name="alteration_source">Source: %1$s</string>
<string name="alteration_target">Target: %1$s</string>
</resources>