Rework the detail system for object / skill / spell / alteration.

This commit is contained in:
Andres Gomez, Thomas (ITDV RL) 2024-06-13 10:55:10 +02:00
parent 6481afb732
commit 244bed9ded
26 changed files with 672 additions and 357 deletions

View file

@ -32,6 +32,7 @@ class SpellRepository @Inject constructor(
) { ) {
private var _spellsBook = MutableStateFlow<List<Spell>>(emptyList()) private var _spellsBook = MutableStateFlow<List<Spell>>(emptyList())
val spellsBook: StateFlow<List<Spell>> get() = _spellsBook val spellsBook: StateFlow<List<Spell>> get() = _spellsBook
private val _spells = MutableStateFlow<Map<String, List<AssignedSpell>>>(emptyMap()) private val _spells = MutableStateFlow<Map<String, List<AssignedSpell>>>(emptyMap())
val spells: StateFlow<Map<String, List<AssignedSpell>>> = val spells: StateFlow<Map<String, List<AssignedSpell>>> =
combine(_spells, firebaseRepository.getAlterationStatus()) { spells, status -> combine(_spells, firebaseRepository.getAlterationStatus()) { spells, status ->

View file

@ -82,8 +82,8 @@ import com.pixelized.rplexicon.ui.screens.character.pages.actions.SpellsViewMode
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPage 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.AlterationPagePreview
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationViewModel 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.composable.chooser.SpellLevelChooser
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellLevelChooserPreview import com.pixelized.rplexicon.ui.screens.character.composable.chooser.SpellLevelChooserPreview
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPagePreview import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPagePreview
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryViewModel import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryViewModel

View file

@ -67,7 +67,7 @@ fun SpellLevelItem(
text = stringResource(id = R.string.spell_level_chooser_available) text = stringResource(id = R.string.spell_level_chooser_available)
) )
Text( Text(
modifier = Modifier.alignByBaseline(), modifier = Modifier.alignByBaseline().padding(start = 4.dp),
style = MaterialTheme.typography.bodySmall, style = MaterialTheme.typography.bodySmall,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
text = "${spell.remaining ?: 0}", text = "${spell.remaining ?: 0}",

View file

@ -1,27 +0,0 @@
package com.pixelized.rplexicon.ui.screens.character.composable.alteration
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetail
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetailUio
@Composable
fun AlterationDetailHandler(
detail: State<AlterationDetailUio?>,
onDismissRequest: () -> Unit,
) {
detail.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
AlterationDetail(
detail = it,
onClose = onDismissRequest,
)
}
}
}

View file

@ -1,11 +1,10 @@
package com.pixelized.rplexicon.ui.screens.character.pages.chooser package com.pixelized.rplexicon.ui.screens.character.composable.chooser
import android.content.res.Configuration.UI_MODE_NIGHT_NO import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material3.Divider
import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface

View file

@ -1,44 +1,47 @@
package com.pixelized.rplexicon.ui.screens.character.pages.alteration package com.pixelized.rplexicon.ui.screens.character.composable.dialogs
import android.content.res.Configuration.UI_MODE_NIGHT_NO import android.content.res.Configuration.UI_MODE_NIGHT_NO
import android.content.res.Configuration.UI_MODE_NIGHT_YES import android.content.res.Configuration.UI_MODE_NIGHT_YES
import androidx.compose.foundation.layout.Arrangement import android.net.Uri
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.FlowRow import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CutCornerShape import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight 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.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.composable.BackgroundImage
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.annotateWithDropCap import com.pixelized.rplexicon.utilitary.annotateWithDropCap
import com.pixelized.rplexicon.utilitary.extentions.lexicon import com.pixelized.rplexicon.utilitary.extentions.lexicon
import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder
@Stable @Stable
data class AlterationDetailUio( data class AlterationDialogDetailUio(
val icon: Uri?,
val name: String, val name: String,
val original: String?, val original: String?,
val source: String, val source: String,
@ -46,71 +49,81 @@ data class AlterationDetailUio(
val description: String, val description: String,
) )
@OptIn(ExperimentalLayoutApi::class)
@Composable @Composable
fun AlterationDetail( fun AlterationDetailDialog(
modifier: Modifier = Modifier, paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 128.dp),
detail: AlterationDetailUio, dialog: State<AlterationDialogDetailUio?>,
onClose: () -> Unit, onDismissRequest: () -> Unit,
) { ) {
Surface( dialog.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
Box(
modifier = Modifier modifier = Modifier
.padding(all = 16.dp) .clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onDismissRequest,
)
.padding(paddingValues = paddingValues),
) {
AlterationDetailDialogContent(
modifier = Modifier
.clickable(
enabled = false,
onClick = { },
)
.ddBorder( .ddBorder(
inner = remember { RoundedCornerShape(size = 8.dp) }, inner = remember { RoundedCornerShape(size = 8.dp) },
outline = remember { CutCornerShape(size = 16.dp) }, outline = remember { CutCornerShape(size = 16.dp) },
)
.then(other = modifier),
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top,
) {
FlowRow(
modifier = Modifier.padding(top = 16.dp),
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Bold,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = annotateWithDropCap(
text = detail.name,
style = MaterialTheme.lexicon.typography.dropCap.titleMedium,
), ),
) detail = it,
detail.original?.let {
Text(
modifier = Modifier.alignByBaseline(),
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic,
style = MaterialTheme.typography.labelSmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
text = it,
) )
} }
} }
IconButton(onClick = onClose) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = null
)
} }
} }
@Composable
private fun AlterationDetailDialogContent(
modifier: Modifier = Modifier,
scrollState: ScrollState = rememberScrollState(),
paddingValues: PaddingValues = PaddingValues(horizontal = 24.dp, vertical = 16.dp),
detail: AlterationDialogDetailUio,
) {
Surface(
modifier = modifier,
) {
Box {
detail.icon?.let { uri ->
BackgroundImage(
modifier = Modifier
.size(size = 144.dp)
.align(alignment = Alignment.TopEnd),
model = uri,
)
}
Column( Column(
modifier = Modifier modifier = Modifier
.padding(top = 8.dp) .verticalScroll(state = scrollState)
.verticalScroll(rememberScrollState()) .padding(paddingValues = paddingValues),
.padding(horizontal = 24.dp),
) { ) {
Text(
style = MaterialTheme.lexicon.typography.base.headlineSmall,
text = annotateWithDropCap(
text = detail.name,
style = MaterialTheme.lexicon.typography.dropCap.headlineSmall,
),
)
Text(
modifier = Modifier.offset(y = -(4.dp)),
style = MaterialTheme.typography.bodyMedium,
fontStyle = FontStyle.Italic,
fontWeight = FontWeight.Light,
text = detail.original ?: "",
)
Text( Text(
fontWeight = FontWeight.Light, fontWeight = FontWeight.Light,
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
@ -122,7 +135,7 @@ fun AlterationDetail(
text = stringResource(id = R.string.alteration_target, detail.target), text = stringResource(id = R.string.alteration_target, detail.target),
) )
Text( Text(
modifier = Modifier.padding(top = 8.dp, bottom = 24.dp), modifier = Modifier.padding(top = 12.dp),
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
text = detail.description, text = detail.description,
) )
@ -136,8 +149,9 @@ fun AlterationDetail(
@Preview(uiMode = UI_MODE_NIGHT_YES) @Preview(uiMode = UI_MODE_NIGHT_YES)
private fun AlterationDetailPreview() { private fun AlterationDetailPreview() {
LexiconTheme { LexiconTheme {
AlterationDetail( AlterationDetailDialogContent(
detail = AlterationDetailUio( detail = AlterationDialogDetailUio(
icon = null,
name = "Rage", name = "Rage",
original = "Rage", original = "Rage",
source = "Barbare", source = "Barbare",
@ -154,7 +168,6 @@ private fun AlterationDetailPreview() {
"Condition \"\"Rage inhibée\"\" :\n" + "Condition \"\"Rage inhibée\"\" :\n" +
"Votre rage vous demande des efforts de concentration ou se dissipe. Vous devez réussir un jet de sauvegarde de constitution dont la difficulté augmente à chaque tour (DC 6 + 2 par tour) sous peine de voir votre rage cesser. Sous certaines conditions, la difficulté pourra augmenter ou baisser au-delà des valeurs indiquées.\"" "Votre rage vous demande des efforts de concentration ou se dissipe. Vous devez réussir un jet de sauvegarde de constitution dont la difficulté augmente à chaque tour (DC 6 + 2 par tour) sous peine de voir votre rage cesser. Sous certaines conditions, la difficulté pourra augmenter ou baisser au-delà des valeurs indiquées.\""
), ),
onClose = { },
) )
} }
} }

View file

@ -0,0 +1,147 @@
package com.pixelized.rplexicon.ui.screens.character.composable.dialogs
import android.content.res.Configuration
import android.net.Uri
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
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 com.pixelized.rplexicon.ui.composable.BackgroundImage
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.annotateWithDropCap
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder
import com.pixelized.rplexicon.utilitary.extentions.string.skillIcon
@Stable
data class SkillDialogDetailUio(
val icon: Uri?,
val name: String,
val original: String?,
val description: String,
)
@Composable
fun SkillDetailDialog(
dialog: State<SkillDialogDetailUio?>,
paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 128.dp),
onDismissRequest: () -> Unit,
) {
dialog.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
Box(
modifier = Modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onDismissRequest,
)
.padding(paddingValues = paddingValues),
) {
SkillDetailDialogContent(
modifier = Modifier
.clickable(
enabled = false,
onClick = { },
)
.ddBorder(
inner = remember { RoundedCornerShape(size = 8.dp) },
outline = remember { CutCornerShape(size = 16.dp) },
),
detail = it,
)
}
}
}
}
@Composable
fun SkillDetailDialogContent(
modifier: Modifier = Modifier,
scrollState: ScrollState = rememberScrollState(),
paddingValues: PaddingValues = PaddingValues(vertical = 16.dp, horizontal = 24.dp),
detail: SkillDialogDetailUio,
) {
Surface(
modifier = modifier,
) {
Box {
detail.icon?.let { uri ->
BackgroundImage(
modifier = Modifier
.size(size = 144.dp)
.align(alignment = Alignment.TopEnd),
model = uri,
)
}
Column(
modifier = Modifier
.verticalScroll(state = scrollState)
.padding(paddingValues = paddingValues),
) {
Text(
style = MaterialTheme.lexicon.typography.base.headlineSmall,
text = annotateWithDropCap(
text = detail.name,
style = MaterialTheme.lexicon.typography.dropCap.headlineSmall,
),
)
Text(
modifier = Modifier.offset(y = -(4.dp)),
style = MaterialTheme.typography.bodyMedium,
fontStyle = FontStyle.Italic,
fontWeight = FontWeight.Light,
text = detail.original ?: "",
)
Text(
modifier = Modifier.padding(top = 12.dp),
style = MaterialTheme.typography.bodyMedium,
text = detail.description,
)
}
}
}
}
@Composable
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun AlterationDetailPreview() {
LexiconTheme {
SkillDetailDialogContent(
detail = SkillDialogDetailUio(
icon = "Endurance implacable".skillIcon(),
name = "Endurance implacable",
original = "Relentless Endurance",
description = "Lorsque vous tombez à 0 point de vie, mais que vous n'êtes pas tué sur le coup, vous pouvez passer à 1 point de vie à la place. Vous devez terminer un repos long avant de pouvoir utiliser cette capacité de nouveau."
),
)
}
}

View file

@ -0,0 +1,271 @@
package com.pixelized.rplexicon.ui.screens.character.composable.dialogs
import android.content.res.Configuration
import android.net.Uri
import androidx.annotation.StringRes
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
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.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
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 com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.composable.BackgroundImage
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.annotateWithDropCap
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder
@Stable
data class SpellDialogDetailUio(
val icon: Uri?,
val name: String,
val translated: String,
val level: String,
@StringRes val school: Int,
val castingTime: String,
val range: String,
val requirement: String,
val duration: String,
val description: String,
val ritual: Boolean,
)
@Composable
fun SpellDetailDialog(
dialog: State<SpellDialogDetailUio?>,
paddingValues: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 128.dp),
onDismissRequest: () -> Unit,
) {
dialog.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
Box(
modifier = Modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = null,
onClick = onDismissRequest,
)
.padding(paddingValues = paddingValues),
) {
SpellDetailDialogContent(
modifier = Modifier
.clickable(
enabled = false,
onClick = { },
)
.ddBorder(
inner = remember { RoundedCornerShape(size = 8.dp) },
outline = remember { CutCornerShape(size = 16.dp) },
),
detail = it,
)
}
}
}
}
@OptIn(ExperimentalLayoutApi::class)
@Composable
private fun SpellDetailDialogContent(
modifier: Modifier = Modifier,
scrollState: ScrollState = rememberScrollState(),
paddingValues: PaddingValues = PaddingValues(vertical = 16.dp, horizontal = 24.dp),
detail: SpellDialogDetailUio,
) {
val typography = MaterialTheme.lexicon.typography
Surface(
modifier = modifier,
) {
Box {
detail.icon?.let { uri ->
BackgroundImage(
modifier = Modifier
.size(size = 144.dp)
.align(alignment = Alignment.TopEnd),
model = uri,
)
}
Column(
modifier = Modifier
.verticalScroll(state = scrollState)
.padding(paddingValues = paddingValues),
) {
Text(
style = typography.base.headlineSmall,
text = annotateWithDropCap(
text = detail.name,
style = typography.dropCap.headlineSmall,
),
)
Text(
modifier = Modifier.offset(y = -(4.dp)),
style = MaterialTheme.typography.bodyMedium,
fontStyle = FontStyle.Italic,
fontWeight = FontWeight.Light,
text = detail.translated,
)
FlowRow(
modifier = Modifier.padding(top = 12.dp),
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_school),
)
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(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_level),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.level,
)
}
FlowRow(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_casting_time),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.castingTime,
)
}
FlowRow(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_range),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.range,
)
}
FlowRow(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_components),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.requirement,
)
}
FlowRow(
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
Text(
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_duration),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.duration,
)
}
Text(
modifier = Modifier.padding(top = 16.dp),
style = MaterialTheme.typography.bodyMedium,
fontWeight = FontWeight.Bold,
text = stringResource(id = R.string.spell_detail_description),
)
Text(
style = MaterialTheme.typography.bodyMedium,
text = detail.description,
)
}
}
}
}
@Composable
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun SpellDetailDialogPreview() {
LexiconTheme {
SpellDetailDialogContent(
detail = SpellDialogDetailUio(
icon = null,
name = "Représailles infernales",
translated = "Hellish Rebuke",
level = "1",
school = R.string.spell_school_evocation,
castingTime = "1 réaction, que vous prenez après avoir subi des dégâts par une créature située à 18 mètres maximum de vous et que vous pouvez voir.",
range = "18 mètres",
requirement = "V, S",
duration = "Instantanée",
description = "Vous pointez votre doigt, et la créature qui vous a infligé des dégâts est momentanément entourée de flammes infernales. La créature doit effectuer un jet de sauvegarde de Dextérité, subissant 2d10 dégâts de fue en cas d'échecn ou la moitié de ces dégâts en cas de réussite.\n\nAux niveaux supérieurs. Lorsque vous lancez ce sort en utilisant un emplacement de sort de niveau 2 ou supérieur, les dégâts sont augmentés de 1d10 pour chaque niveau d'emplacement au-dela du niveau 1.",
ritual = false,
),
)
}
}

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellLevelUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellLevelUio
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellChooserUio import com.pixelized.rplexicon.ui.screens.character.composable.chooser.SpellChooserUio
@Composable @Composable
@Stable @Stable

View file

@ -30,7 +30,7 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
), ),
armorClass = LabelPointUio( armorClass = LabelPointUio(
label = R.string.character_sheet_title_ca, label = R.string.character_sheet_title_ca,
value = sheetHeaderData?.ca?.let { "$it" } ?: " ", value = sheetHeaderData?.ca?.let { "$it" } ?: "?",
max = null, max = null,
), ),
hitPoint = LabelPointUio( hitPoint = LabelPointUio(
@ -80,7 +80,7 @@ class CharacterSheetHeaderUioFactory @Inject constructor(
} }
else -> when { else -> when {
fireHeaderData?.wildShapeHp == null -> sheetHeaderData?.hpMax?.let { "$it" } ?: "?" fireHeaderData.wildShapeHp == null -> sheetHeaderData?.hpMax?.let { "$it" } ?: "?"
fireHeaderData.extraHp == 0 -> "${fireHeaderData.wildShapeHp}" fireHeaderData.extraHp == 0 -> "${fireHeaderData.wildShapeHp}"
else -> "${fireHeaderData.wildShapeHp}+${fireHeaderData.extraHp}" else -> "${fireHeaderData.wildShapeHp}+${fireHeaderData.extraHp}"
} }

View file

@ -27,8 +27,6 @@ import com.pixelized.rplexicon.LocalRollOverlay
import com.pixelized.rplexicon.R import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog
import com.pixelized.rplexicon.ui.composable.edit.HandleSpellEditDialog import com.pixelized.rplexicon.ui.composable.edit.HandleSpellEditDialog
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.screens.navigateToSpellDetail
import com.pixelized.rplexicon.ui.screens.character.composable.actions.Attack import com.pixelized.rplexicon.ui.screens.character.composable.actions.Attack
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AttackUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.AttackUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.GenericHeader import com.pixelized.rplexicon.ui.screens.character.composable.actions.GenericHeader
@ -44,6 +42,8 @@ import com.pixelized.rplexicon.ui.screens.character.composable.actions.rememberS
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberAttackListStatePreview import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberAttackListStatePreview
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberObjectListStatePreview import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberObjectListStatePreview
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberSpellListStatePreview import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberSpellListStatePreview
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDetailDialog
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SpellDetailDialog
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -56,7 +56,6 @@ fun ActionPage(
spellsViewModel: SpellsViewModel = hiltViewModel(), spellsViewModel: SpellsViewModel = hiltViewModel(),
skillViewModel: SkillsViewModel = hiltViewModel(), skillViewModel: SkillsViewModel = hiltViewModel(),
) { ) {
val screen = LocalScreenNavHost.current
val overlay = LocalRollOverlay.current val overlay = LocalRollOverlay.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
@ -83,7 +82,7 @@ fun ActionPage(
} }
}, },
onObject = { onObject = {
skillViewModel.showSkillDetailDialog(item = it.name) objectsViewModel.showObjectDetailDialog(item = it.name)
}, },
onUseObject = { onUseObject = {
objectsViewModel.onUse(it.name)?.let { throws -> objectsViewModel.onUse(it.name)?.let { throws ->
@ -103,13 +102,17 @@ fun ActionPage(
} }
}, },
onSkillInfo = { onSkillInfo = {
if (spellsViewModel.isSpell(name = it.label)) {
spellsViewModel.showSpellDetailDialog(item = it.label)
} else {
skillViewModel.showSkillDetailDialog(item = it.label) skillViewModel.showSkillDetailDialog(item = it.label)
}
}, },
onSpellLevel = { level: Int, value: Int, max: Int -> onSpellLevel = { level: Int, value: Int, max: Int ->
spellsViewModel.showSpellEditDialog(level = level, value = value, max = max) spellsViewModel.showSpellEditDialog(level = level, value = value, max = max)
}, },
onSpell = { spell -> onSpell = { spell ->
screen.navigateToSpellDetail(spell = spell) spellsViewModel.showSpellDetailDialog(item = spell)
}, },
onSpellHit = { id -> onSpellHit = { id ->
scope.launch { scope.launch {
@ -142,16 +145,26 @@ fun ActionPage(
onConfirm = spellsViewModel::applySpellChange onConfirm = spellsViewModel::applySpellChange
) )
SpellDetailDialog(
dialog = spellsViewModel.spellDetailDialog,
onDismissRequest = spellsViewModel::hideSpellDetailDialog
)
HandleSkillEditDialog( HandleSkillEditDialog(
dialog = skillViewModel.skillEditDialog, dialog = skillViewModel.skillEditDialog,
onDismissRequest = skillViewModel::hideSkillEditDialog, onDismissRequest = skillViewModel::hideSkillEditDialog,
onConfirm = skillViewModel::applySkillChange onConfirm = skillViewModel::applySkillChange
) )
HandleSkillDetailDialog( SkillDetailDialog(
dialog = skillViewModel.skillDetailDialog, dialog = skillViewModel.skillDetailDialog,
onDismissRequest = skillViewModel::hideSkillDetailDialog onDismissRequest = skillViewModel::hideSkillDetailDialog
) )
SkillDetailDialog(
dialog = objectsViewModel.objectDetailDialog,
onDismissRequest = objectsViewModel::hideObjectDetailDialog
)
} }
@OptIn(ExperimentalFoundationApi::class) @OptIn(ExperimentalFoundationApi::class)

View file

@ -10,6 +10,7 @@ import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.actions.ObjectItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.ObjectItemUio
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDialogDetailUio
import com.pixelized.rplexicon.utilitary.extentions.string.objectIcon import com.pixelized.rplexicon.utilitary.extentions.string.objectIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -28,8 +29,8 @@ class ObjectsViewModel @Inject constructor(
private val _objects = mutableStateOf<List<ObjectItemUio>>(emptyList()) private val _objects = mutableStateOf<List<ObjectItemUio>>(emptyList())
val objects: State<List<ObjectItemUio>> get() = _objects val objects: State<List<ObjectItemUio>> get() = _objects
private val _dialog = mutableStateOf<SkillDetailUio?>(null) private val _objectDetailDialog = mutableStateOf<SkillDialogDetailUio?>(null)
val dialog: State<SkillDetailUio?> get() = _dialog val objectDetailDialog: State<SkillDialogDetailUio?> get() = _objectDetailDialog
init { init {
viewModelScope.launch(Dispatchers.Default) { viewModelScope.launch(Dispatchers.Default) {
@ -60,4 +61,21 @@ class ObjectsViewModel @Inject constructor(
) )
} }
} }
fun showObjectDetailDialog(item: String) {
val description = descriptionRepository.getDescription(name = item)
val item = objectsRepository.find(character = character, item = item)
if (item != null && description != null) {
_objectDetailDialog.value = SkillDialogDetailUio(
icon = item.icon ?: item.name.objectIcon(),
name = item.name,
original = description.original,
description = description.description
)
}
}
fun hideObjectDetailDialog() {
_objectDetailDialog.value = null
}
} }

View file

@ -1,161 +0,0 @@
package com.pixelized.rplexicon.ui.screens.character.pages.actions
import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CutCornerShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Close
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontStyle
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 androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.lexicon
import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder
@Stable
data class SkillDetailUio(
val name: String,
val original: String?,
val description: String,
)
@OptIn(ExperimentalLayoutApi::class)
@Composable
fun SkillDetail(
modifier: Modifier = Modifier,
detail: SkillDetailUio,
onClose: () -> Unit,
) {
Surface(
modifier = Modifier
.padding(all = 16.dp)
.ddBorder(
inner = remember { RoundedCornerShape(size = 8.dp) },
outline = remember { CutCornerShape(size = 16.dp) },
)
.then(other = modifier),
) {
Column {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(start = 24.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.Top,
) {
FlowRow(
modifier = Modifier
.padding(top = 16.dp)
.weight(weight = 1f),
horizontalArrangement = Arrangement.spacedBy(4.dp),
) {
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.titleMedium,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
text = AnnotatedString(
text = detail.name,
spanStyles = listOf(
AnnotatedString.Range(
item = MaterialTheme.lexicon.typography.dropCap.titleMedium,
start = 0,
end = Integer.min(1, detail.name.length),
)
)
),
)
detail.original?.let {
Text(
modifier = Modifier.alignByBaseline(),
fontWeight = FontWeight.Light,
fontStyle = FontStyle.Italic,
style = MaterialTheme.typography.labelSmall,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
text = it,
)
}
}
IconButton(onClick = onClose) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = null
)
}
}
Column(
modifier = Modifier
.padding(top = 8.dp)
.verticalScroll(rememberScrollState())
.padding(horizontal = 24.dp),
) {
Text(
modifier = Modifier.padding(top = 8.dp, bottom = 24.dp),
style = MaterialTheme.typography.bodyMedium,
text = detail.description,
)
}
}
}
}
@Composable
fun HandleSkillDetailDialog(
dialog: State<SkillDetailUio?>,
onDismissRequest: () -> Unit,
) {
dialog.value?.let {
Dialog(
properties = remember { DialogProperties(usePlatformDefaultWidth = false) },
onDismissRequest = onDismissRequest,
) {
SkillDetail(
detail = it,
onClose = onDismissRequest,
)
}
}
}
@Composable
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
private fun AlterationDetailPreview() {
LexiconTheme {
SkillDetail(
detail = SkillDetailUio(
name = "Endurance implacable",
original = "Relentless Endurance",
description = "Lorsque vous tombez à 0 point de vie, mais que vous n'êtes pas tué sur le coup, vous pouvez passer à 1 point de vie à la place. Vous devez terminer un repos long avant de pouvoir utiliser cette capacité de nouveau."
),
onClose = { },
)
}
}

View file

@ -18,6 +18,8 @@ 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.actions.SkillItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.SkillItemUio
import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDialogDetailUio
import com.pixelized.rplexicon.utilitary.extentions.string.skillIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -41,8 +43,8 @@ class SkillsViewModel @Inject constructor(
private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null) private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null)
val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog
private val _skillDetailDialog = mutableStateOf<SkillDetailUio?>(null) private val _skillDetailDialog = mutableStateOf<SkillDialogDetailUio?>(null)
val skillDetailDialog: State<SkillDetailUio?> get() = _skillDetailDialog val skillDetailDialog: State<SkillDialogDetailUio?> get() = _skillDetailDialog
private val _skills = mutableStateOf<List<SkillItemUio>>(emptyList()) private val _skills = mutableStateOf<List<SkillItemUio>>(emptyList())
val skills: State<List<SkillItemUio>> get() = _skills val skills: State<List<SkillItemUio>> get() = _skills
@ -81,11 +83,12 @@ class SkillsViewModel @Inject constructor(
) )
fun showSkillDetailDialog(item: String) { fun showSkillDetailDialog(item: String) {
_skillDetailDialog.value = descriptionRepository val description = descriptionRepository.getDescription(name = item)
.getDescription(name = item) val skill = skillRepository.find(character = character, skill = item)
?.let { description -> if (skill != null && description != null) {
SkillDetailUio( _skillDetailDialog.value = SkillDialogDetailUio(
name = item, icon = skill.icon ?: skill.name.skillIcon(),
name = skill.name,
original = description.original, original = description.original,
description = description.description description = description.description
) )

View file

@ -16,19 +16,23 @@ import com.pixelized.rplexicon.data.model.roll.Throw
import com.pixelized.rplexicon.data.network.CharacterSheetFire import com.pixelized.rplexicon.data.network.CharacterSheetFire
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.data.repository.character.SpellRepository import com.pixelized.rplexicon.data.repository.character.SpellRepository
import com.pixelized.rplexicon.ui.composable.edit.SpellEditDialogUio import com.pixelized.rplexicon.ui.composable.edit.SpellEditDialogUio
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellLevelUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellLevelUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
import com.pixelized.rplexicon.ui.screens.character.pages.chooser.SpellChooserUio import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SpellDialogDetailUio
import com.pixelized.rplexicon.ui.screens.character.composable.chooser.SpellChooserUio
import com.pixelized.rplexicon.utilitary.extentions.icon import com.pixelized.rplexicon.utilitary.extentions.icon
import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot
import com.pixelized.rplexicon.utilitary.extentions.local.highestSpellLevel import com.pixelized.rplexicon.utilitary.extentions.local.highestSpellLevel
import com.pixelized.rplexicon.utilitary.extentions.local.label
import com.pixelized.rplexicon.utilitary.extentions.local.spell import com.pixelized.rplexicon.utilitary.extentions.local.spell
import com.pixelized.rplexicon.utilitary.extentions.modifier import com.pixelized.rplexicon.utilitary.extentions.modifier
import com.pixelized.rplexicon.utilitary.extentions.signLabel import com.pixelized.rplexicon.utilitary.extentions.signLabel
import com.pixelized.rplexicon.utilitary.extentions.string.spellIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -44,6 +48,7 @@ class SpellsViewModel @Inject constructor(
private val characterRepository: CharacterSheetRepository, private val characterRepository: CharacterSheetRepository,
private val firebaseRepository: FirebaseRepository, private val firebaseRepository: FirebaseRepository,
private val spellRepository: SpellRepository, private val spellRepository: SpellRepository,
private val descriptionRepository: DescriptionRepository,
application: Application, application: Application,
spellBookUseCase: SpellBookUseCase, spellBookUseCase: SpellBookUseCase,
savedStateHandle: SavedStateHandle, savedStateHandle: SavedStateHandle,
@ -52,6 +57,9 @@ class SpellsViewModel @Inject constructor(
private var characterFire: CharacterSheetFire? = null private var characterFire: CharacterSheetFire? = null
private val characterName = savedStateHandle.characterSheetArgument.name private val characterName = savedStateHandle.characterSheetArgument.name
private val _spellDetailDialog = mutableStateOf<SpellDialogDetailUio?>(null)
val spellDetailDialog: State<SpellDialogDetailUio?> get() = _spellDetailDialog
private val _editDialog = mutableStateOf<SpellEditDialogUio?>(null) private val _editDialog = mutableStateOf<SpellEditDialogUio?>(null)
val spellEditDialog: State<SpellEditDialogUio?> get() = _editDialog val spellEditDialog: State<SpellEditDialogUio?> get() = _editDialog
@ -171,6 +179,34 @@ class SpellsViewModel @Inject constructor(
hideSpellEditDialog() hideSpellEditDialog()
} }
fun isSpell(name: String): Boolean {
return spellRepository.findSpell(name = name) != null
}
fun showSpellDetailDialog(item: String) {
val description = descriptionRepository.getDescription(name = item)
val spell = spellRepository.findSpell(name = item)
if (spell != null && description != null) {
_spellDetailDialog.value = SpellDialogDetailUio(
icon = spell.icon ?: spell.name.spellIcon(),
name = spell.name,
translated = description.original,
level = "${spell.level}",
school = spell.school.label,
castingTime = spell.castingTime,
range = spell.range,
requirement = spell.requirement,
duration = spell.duration,
description = description.description,
ritual = spell.ritual,
)
}
}
fun hideSpellDetailDialog() {
_spellDetailDialog.value = null
}
/** /**
* Helper method to build a readable String from a Throw. * Helper method to build a readable String from a Throw.
* Create a string following the format "amount 'd' faces '+' modifiers + amount * level 'd' faces" * Create a string following the format "amount 'd' faces '+' modifiers + amount * level 'd' faces"

View file

@ -20,7 +20,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.rplexicon.ui.composable.CategoryHeader import com.pixelized.rplexicon.ui.composable.CategoryHeader
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItem import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItem
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItemUio
import com.pixelized.rplexicon.ui.screens.character.composable.alteration.AlterationDetailHandler import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDetailDialog
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -52,9 +52,9 @@ fun AlterationPage(
}, },
) )
AlterationDetailHandler( AlterationDetailDialog(
detail = viewModel.alterationDetail, dialog = viewModel.alterationDetailDialog,
onDismissRequest = { viewModel.hideAlterationDetail() }, onDismissRequest = viewModel::hideAlterationDetail,
) )
} }

View file

@ -19,8 +19,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.DescriptionRepository import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDialogDetailUio
import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory
import com.pixelized.rplexicon.utilitary.extentions.context import com.pixelized.rplexicon.utilitary.extentions.context
import com.pixelized.rplexicon.utilitary.extentions.string.alterationIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -45,8 +47,8 @@ class AlterationViewModel @Inject constructor(
private val _alterations = mutableStateOf<List<AlterationGroupUio>>(emptyList()) private val _alterations = mutableStateOf<List<AlterationGroupUio>>(emptyList())
val alterations: State<List<AlterationGroupUio>> get() = _alterations val alterations: State<List<AlterationGroupUio>> get() = _alterations
private val _alterationDetail = mutableStateOf<AlterationDetailUio?>(null) private val _alterationDetailDialog = mutableStateOf<AlterationDialogDetailUio?>(null)
val alterationDetail: State<AlterationDetailUio?> get() = _alterationDetail val alterationDetailDialog: State<AlterationDialogDetailUio?> get() = _alterationDetailDialog
init { init {
viewModelScope.launch { viewModelScope.launch {
@ -114,7 +116,8 @@ class AlterationViewModel @Inject constructor(
val description = descriptionRepository.getDescription( val description = descriptionRepository.getDescription(
name = alteration.name, name = alteration.name,
) )
_alterationDetail.value = AlterationDetailUio( _alterationDetailDialog.value = AlterationDialogDetailUio(
icon = alteration.icon ?: alteration.name.alterationIcon(),
name = id, name = id,
original = description?.original, original = description?.original,
source = alteration.source, source = alteration.source,
@ -126,7 +129,7 @@ class AlterationViewModel @Inject constructor(
} }
fun hideAlterationDetail() { fun hideAlterationDetail() {
_alterationDetail.value = null _alterationDetailDialog.value = null
} }
private data class AlterationStruct( private data class AlterationStruct(

View file

@ -27,7 +27,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.actions.Inventory
import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberEquipmentState import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberEquipmentState
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberInventoryListState import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberInventoryListState
import com.pixelized.rplexicon.ui.screens.character.pages.actions.HandleSkillDetailDialog import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDetailDialog
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -50,7 +50,7 @@ fun InventoryPage(
}, },
) )
HandleSkillDetailDialog( SkillDetailDialog(
dialog = viewModel.dialog, dialog = viewModel.dialog,
onDismissRequest = viewModel::hideSkillDetailDialog, onDismissRequest = viewModel::hideSkillDetailDialog,
) )

View file

@ -14,8 +14,9 @@ import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
import com.pixelized.rplexicon.ui.screens.character.composable.actions.EquipmentItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.EquipmentItemUio
import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio
import com.pixelized.rplexicon.ui.screens.character.factory.ItemUioFactory import com.pixelized.rplexicon.ui.screens.character.factory.ItemUioFactory
import com.pixelized.rplexicon.ui.screens.character.pages.actions.SkillDetailUio import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDialogDetailUio
import com.pixelized.rplexicon.utilitary.extentions.context import com.pixelized.rplexicon.utilitary.extentions.context
import com.pixelized.rplexicon.utilitary.extentions.string.equipmentsIcon
import com.pixelized.rplexicon.utilitary.extentions.uri import com.pixelized.rplexicon.utilitary.extentions.uri
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -42,8 +43,8 @@ class InventoryViewModel @Inject constructor(
private val _inventory = mutableStateOf<List<InventoryItemUio>>(emptyList()) private val _inventory = mutableStateOf<List<InventoryItemUio>>(emptyList())
val inventory: State<List<InventoryItemUio>> get() = _inventory val inventory: State<List<InventoryItemUio>> get() = _inventory
private val _dialog = mutableStateOf<SkillDetailUio?>(null) private val _dialog = mutableStateOf<SkillDialogDetailUio?>(null)
val dialog: State<SkillDetailUio?> get() = _dialog val dialog: State<SkillDialogDetailUio?> get() = _dialog
private val _snack = MutableSharedFlow<String?>() private val _snack = MutableSharedFlow<String?>()
val snack: SharedFlow<String?> get() = _snack val snack: SharedFlow<String?> get() = _snack
@ -89,9 +90,9 @@ class InventoryViewModel @Inject constructor(
fun showSkillDetailDialog(item: String) { fun showSkillDetailDialog(item: String) {
val description = descriptionRepository.getDescription(name = item) val description = descriptionRepository.getDescription(name = item)
if (description != null) { if (description != null) {
_dialog.value = SkillDetailUio( _dialog.value = SkillDialogDetailUio(
icon = item.equipmentsIcon(),
name = item, name = item,
original = description.original, original = description.original,
description = description.description description = description.description

View file

@ -53,7 +53,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.character.Profici
import com.pixelized.rplexicon.ui.screens.character.composable.character.Stat import com.pixelized.rplexicon.ui.screens.character.composable.character.Stat
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterSheetStatePreview import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberCharacterSheetStatePreview
import com.pixelized.rplexicon.ui.screens.character.pages.actions.HandleSkillDetailDialog import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDetailDialog
import com.pixelized.rplexicon.ui.theme.LexiconTheme import com.pixelized.rplexicon.ui.theme.LexiconTheme
import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder import com.pixelized.rplexicon.utilitary.extentions.modifier.ddBorder
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -113,7 +113,7 @@ fun ProficiencyPage(
onConfirm = viewModel::applySkillChange onConfirm = viewModel::applySkillChange
) )
HandleSkillDetailDialog( SkillDetailDialog(
dialog = viewModel.skillDetailDialog, dialog = viewModel.skillDetailDialog,
onDismissRequest = viewModel::hideSkillDetailDialog onDismissRequest = viewModel::hideSkillDetailDialog
) )

View file

@ -24,8 +24,9 @@ import com.pixelized.rplexicon.ui.screens.character.composable.character.Profici
import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio import com.pixelized.rplexicon.ui.screens.character.composable.character.StatUio
import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetUioFactory import com.pixelized.rplexicon.ui.screens.character.factory.CharacterSheetUioFactory
import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory import com.pixelized.rplexicon.ui.screens.character.factory.SkillFactoryUioFactory
import com.pixelized.rplexicon.ui.screens.character.pages.actions.SkillDetailUio import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.SkillDialogDetailUio
import com.pixelized.rplexicon.utilitary.extentions.local.toStatus import com.pixelized.rplexicon.utilitary.extentions.local.toStatus
import com.pixelized.rplexicon.utilitary.extentions.string.skillIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -53,8 +54,8 @@ class ProficiencyViewModel @Inject constructor(
private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null) private val _skillEditDialog = mutableStateOf<SkillEditDialogUio?>(null)
val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog val skillEditDialog: State<SkillEditDialogUio?> get() = _skillEditDialog
private val _skillDetailDialog = mutableStateOf<SkillDetailUio?>(null) private val _skillDetailDialog = mutableStateOf<SkillDialogDetailUio?>(null)
val skillDetailDialog: State<SkillDetailUio?> get() = _skillDetailDialog val skillDetailDialog: State<SkillDialogDetailUio?> get() = _skillDetailDialog
private val _skills = mutableStateOf<List<SkillItemUio>>(emptyList()) private val _skills = mutableStateOf<List<SkillItemUio>>(emptyList())
val skills: State<List<SkillItemUio>> get() = _skills val skills: State<List<SkillItemUio>> get() = _skills
@ -154,11 +155,12 @@ class ProficiencyViewModel @Inject constructor(
) )
fun showSkillDetailDialog(item: String) { fun showSkillDetailDialog(item: String) {
_skillDetailDialog.value = descriptionRepository val description = descriptionRepository.getDescription(name = item)
.getDescription(name = item) val skill = skillRepository.find(character = character, skill = item)
?.let { description -> if (skill != null && description != null) {
SkillDetailUio( _skillDetailDialog.value = SkillDialogDetailUio(
name = item, icon = skill.icon ?: skill.name.skillIcon(),
name = skill.name,
original = description.original, original = description.original,
description = description.description description = description.description
) )

View file

@ -66,8 +66,6 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp 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 androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.rplexicon.LocalRollOverlay import com.pixelized.rplexicon.LocalRollOverlay
import com.pixelized.rplexicon.NO_WINDOW_INSETS import com.pixelized.rplexicon.NO_WINDOW_INSETS
@ -77,9 +75,8 @@ import com.pixelized.rplexicon.ui.composable.BlurredOverlayHostState
import com.pixelized.rplexicon.ui.composable.CategoryHeader import com.pixelized.rplexicon.ui.composable.CategoryHeader
import com.pixelized.rplexicon.ui.composable.ModalNavigationDrawer import com.pixelized.rplexicon.ui.composable.ModalNavigationDrawer
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItem import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItem
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetail
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetailUio
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationGroupUio import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationGroupUio
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDetailDialog
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDice 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.RollDiceUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
@ -136,9 +133,9 @@ fun RollOverlay(
onBack = { scope.launch { drawer.close() } }, onBack = { scope.launch { drawer.close() } },
) )
AlterationDetailHandler( AlterationDetailDialog(
detail = viewModel.alterationDetail, dialog = viewModel.alterationDetailDialog,
onDismissRequest = { viewModel.hideAlterationDetail() }, onDismissRequest = viewModel::hideAlterationDetail,
) )
} }
@ -344,24 +341,6 @@ private fun Modifier.detailPaddingBottom(
this.then(other = Modifier.padding(bottom = padding)) this.then(other = Modifier.padding(bottom = padding))
} }
@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 @Composable
@Preview(uiMode = UI_MODE_NIGHT_NO) @Preview(uiMode = UI_MODE_NIGHT_NO)
@Preview(uiMode = UI_MODE_NIGHT_YES) @Preview(uiMode = UI_MODE_NIGHT_YES)

View file

@ -20,14 +20,15 @@ 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.DescriptionRepository import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.AlterationItemUio
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetailUio
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationGroupUio import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationGroupUio
import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDialogDetailUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory
import com.pixelized.rplexicon.ui.screens.rolls.factory.DiceFactory import com.pixelized.rplexicon.ui.screens.rolls.factory.DiceFactory
import com.pixelized.rplexicon.utilitary.extentions.context import com.pixelized.rplexicon.utilitary.extentions.context
import com.pixelized.rplexicon.utilitary.extentions.string.alterationIcon
import com.pixelized.rplexicon.utilitary.extentions.switch import com.pixelized.rplexicon.utilitary.extentions.switch
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -85,8 +86,8 @@ class RollOverlayViewModel @Inject constructor(
private val _isThrowHidden = mutableStateOf(false) private val _isThrowHidden = mutableStateOf(false)
val isThrowHidden: State<Boolean> get() = _isThrowHidden val isThrowHidden: State<Boolean> get() = _isThrowHidden
private val _alterationDetail = mutableStateOf<AlterationDetailUio?>(null) private val _alterationDetailDialog = mutableStateOf<AlterationDialogDetailUio?>(null)
val alterationDetail: State<AlterationDetailUio?> get() = _alterationDetail val alterationDetailDialog: State<AlterationDialogDetailUio?> get() = _alterationDetailDialog
suspend fun prepareRoll(diceThrow: DiceThrow) { suspend fun prepareRoll(diceThrow: DiceThrow) {
this.diceThrow = diceThrow this.diceThrow = diceThrow
@ -190,7 +191,8 @@ class RollOverlayViewModel @Inject constructor(
name = alteration?.name, name = alteration?.name,
) )
if (alteration != null) { if (alteration != null) {
_alterationDetail.value = AlterationDetailUio( _alterationDetailDialog.value = AlterationDialogDetailUio(
icon = alteration.icon ?: alteration.name.alterationIcon(),
name = id, name = id,
original = description?.original, original = description?.original,
source = alteration.source, source = alteration.source,
@ -202,7 +204,7 @@ class RollOverlayViewModel @Inject constructor(
} }
fun hideAlterationDetail() { fun hideAlterationDetail() {
_alterationDetail.value = null _alterationDetailDialog.value = null
} }
private data class AlterationStruct( private data class AlterationStruct(

View file

@ -44,7 +44,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.navigation.LocalScreenNavHost import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet
import com.pixelized.rplexicon.ui.screens.character.composable.alteration.AlterationDetailHandler import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDetailDialog
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard 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.composable.ThrowsCardUio
import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummary import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummary
@ -124,8 +124,8 @@ fun SummaryScreen(
onDetail = { statisticsViewModel.hideDetail() }, onDetail = { statisticsViewModel.hideDetail() },
) )
AlterationDetailHandler( AlterationDetailDialog(
detail = statisticsViewModel.alterationDetail, dialog = statisticsViewModel.alterationDetailDialog,
onDismissRequest = { statisticsViewModel.hideAlterationDetail() }, onDismissRequest = { statisticsViewModel.hideAlterationDetail() },
) )
} }

View file

@ -9,11 +9,12 @@ import com.pixelized.rplexicon.R
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
import com.pixelized.rplexicon.data.repository.character.AlterationRepository import com.pixelized.rplexicon.data.repository.character.AlterationRepository
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetailUio import com.pixelized.rplexicon.ui.screens.character.composable.dialogs.AlterationDialogDetailUio
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryUio import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryUio
import com.pixelized.rplexicon.utilitary.extentions.context import com.pixelized.rplexicon.utilitary.extentions.context
import com.pixelized.rplexicon.utilitary.extentions.string.alterationIcon
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -38,8 +39,8 @@ class StatisticViewModel @Inject constructor(
private val _detail = mutableStateOf<ThrowsCardUio?>(null) private val _detail = mutableStateOf<ThrowsCardUio?>(null)
val detail: State<ThrowsCardUio?> get() = _detail val detail: State<ThrowsCardUio?> get() = _detail
private val _alterationDetail = mutableStateOf<AlterationDetailUio?>(null) private val _alterationDetailDialog = mutableStateOf<AlterationDialogDetailUio?>(null)
val alterationDetail: State<AlterationDetailUio?> get() = _alterationDetail val alterationDetailDialog: State<AlterationDialogDetailUio?> get() = _alterationDetailDialog
fun showDetail(dice: ClassHeaderSummaryUio.Dice) { fun showDetail(dice: ClassHeaderSummaryUio.Dice) {
detailJob?.cancel() detailJob?.cancel()
@ -70,7 +71,8 @@ class StatisticViewModel @Inject constructor(
val description = descriptionRepository.getDescription(name = alteration?.name) val description = descriptionRepository.getDescription(name = alteration?.name)
if (alteration != null) { if (alteration != null) {
_alterationDetail.value = AlterationDetailUio( _alterationDetailDialog.value = AlterationDialogDetailUio(
icon = alteration.icon ?: alteration.name.alterationIcon(),
name = name, name = name,
original = description?.original, original = description?.original,
source = alteration.source, source = alteration.source,
@ -82,6 +84,6 @@ class StatisticViewModel @Inject constructor(
} }
fun hideAlterationDetail() { fun hideAlterationDetail() {
_alterationDetail.value = null _alterationDetailDialog.value = null
} }
} }

View file

@ -12,6 +12,10 @@ fun String.objectIcon(): Uri? {
return ResourcesCache.objects[this]?.uri?.toUriOrNull() return ResourcesCache.objects[this]?.uri?.toUriOrNull()
} }
fun String.equipmentsIcon(): Uri? {
return ResourcesCache.equipments[this]?.uri?.toUriOrNull()
}
fun String.alterationIcon(): Uri? { fun String.alterationIcon(): Uri? {
return ResourcesCache.alterations[this]?.uri?.toUriOrNull() return ResourcesCache.alterations[this]?.uri?.toUriOrNull()
} }
@ -112,6 +116,15 @@ private object ResourcesCache {
"Baies nourricières" to R.drawable.icbg_food_goodberry_unfaded, "Baies nourricières" to R.drawable.icbg_food_goodberry_unfaded,
) )
val equipments = hashMapOf(
"Dague" to R.drawable.icbg_dagger_unfaded,
"Hache de guerre en argent" to R.drawable.icbg_battleaxe_plus_one_unfaded,
"Bouclier" to R.drawable.icbg_studded_shield_unfaded,
"Cape de protection" to R.drawable.icbg_cloak_of_protection_unfaded,
"Armure d'écailles" to R.drawable.icbg_scale_mail_unfaded,
"Armure de cuir" to R.drawable.icbg_leather_armour_rogue_unfaded,
)
val skills = hashMapOf( val skills = hashMapOf(
"Dé de vie (Barbare)" to R.drawable.icbg_bolstering_magic_boon, "Dé de vie (Barbare)" to R.drawable.icbg_bolstering_magic_boon,
"Dé de vie (Guerrier)" to R.drawable.icbg_bolstering_magic_boon, "Dé de vie (Guerrier)" to R.drawable.icbg_bolstering_magic_boon,