From e880d37275fe7d0a4a2c91e98a75d313adc973ff Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Fri, 15 Nov 2024 15:42:19 +0100 Subject: [PATCH] Add diminished status management. --- .../composeResources/drawable/ic_d20_32dp.xml | 1 + .../drawable/ic_skull_32dp.xml | 20 +++ .../composeResources/values/strings.xml | 1 + .../CharacterSheetRepository.kt | 21 +++ .../detail/CharacterSheetFactory.kt | 16 +- .../detail/CharacterSheetPage.kt | 61 +++++++- .../detail/CharacterSheetViewModel.kt | 76 ++++++++-- .../detail/dialog/CharacterSheetStatDialog.kt | 83 ++++++----- .../detail/dialog/DiminishedStatDialog.kt | 139 ++++++++++++++++++ .../desktop/lwa/screen/roll/RollViewModel.kt | 4 +- 10 files changed, 371 insertions(+), 51 deletions(-) create mode 100644 composeApp/src/commonMain/composeResources/drawable/ic_skull_32dp.xml create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_d20_32dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_d20_32dp.xml index 76d9633..dfcf285 100644 --- a/composeApp/src/commonMain/composeResources/drawable/ic_d20_32dp.xml +++ b/composeApp/src/commonMain/composeResources/drawable/ic_d20_32dp.xml @@ -1,3 +1,4 @@ + + + + + + + + \ No newline at end of file diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 007a151..eff5a11 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -58,6 +58,7 @@ Compétences magiques Ajouter une compétence magique + État diminuer Force Dextérité Constitution diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt index 92dd144..fc33978 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt @@ -2,6 +2,7 @@ package com.pixelized.desktop.lwa.repository.characterSheet import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map @@ -18,6 +19,8 @@ object CharacterSheetRepository { initialValue = emptyList() ) + private val diminished = MutableStateFlow>(emptyMap()) + fun characterSheetFlow(): StateFlow> { return sheets } @@ -34,6 +37,18 @@ object CharacterSheetRepository { ) } + fun characterDiminishedFlow(id: String?): StateFlow { + return diminished + .map { + it[id] ?: 0 + } + .stateIn( + scope = scope, + started = SharingStarted.Eagerly, + initialValue = diminished.value[id] ?: 0 + ) + } + fun save(characterSheet: CharacterSheet) { val savedSheets = store.load().toMutableList() val savedIndex = savedSheets.indexOfFirst { it.id == characterSheet.id } @@ -53,5 +68,11 @@ object CharacterSheetRepository { savedSheets.removeIf { it.id == id } store.save(sheets = savedSheets) } + + fun setDiminishedForCharacter(id: String, diminished: Int) { + this.diminished.value = this.diminished.value.toMutableMap().apply { + this[id] = diminished + } + } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt index 46199fd..894b465 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetFactory.kt @@ -17,6 +17,7 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_cha import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__movement import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point import org.jetbrains.compose.resources.getString +import kotlin.math.max class CharacterSheetFactory { @@ -25,7 +26,10 @@ class CharacterSheetFactory { const val PP = "PP" } - suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio { + suspend fun convertToUio( + model: CharacterSheet, + diminished: Int, + ): CharacterSheetPageUio { return CharacterSheetPageUio( id = model.id, name = model.name, @@ -109,7 +113,7 @@ class CharacterSheetFactory { if (it.value > 0) { Node( label = it.label, - value = it.value, + value = it.value.diminished(diminished), used = it.used, ) } else { @@ -120,7 +124,7 @@ class CharacterSheetFactory { if (it.value > 0) { Node( label = it.label, - value = it.value, + value = it.value.diminished(diminished), used = it.used, ) } else { @@ -131,7 +135,7 @@ class CharacterSheetFactory { if (it.value > 0) { Node( label = it.label, - value = it.value, + value = it.value.diminished(diminished), used = it.used, ) } else { @@ -151,3 +155,7 @@ class CharacterSheetFactory { ) } } + +fun Int.diminished(value: Int): Int { + return max(0, this - value) +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt index 888cc62..a7c388a 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt @@ -1,6 +1,7 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.SizeTransform import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically @@ -11,6 +12,7 @@ import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight @@ -37,6 +39,7 @@ import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Edit import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable +import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment @@ -56,6 +59,7 @@ import com.pixelized.desktop.lwa.navigation.screen.destination.navigateToCharact import com.pixelized.desktop.lwa.navigation.window.LocalWindow import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialog import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.CharacterSheetStatDialog +import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.DiminishedStatDialog import com.pixelized.desktop.lwa.screen.roll.RollPage import com.pixelized.desktop.lwa.screen.roll.RollViewModel import kotlinx.coroutines.launch @@ -65,6 +69,7 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__occupat import lwacharactersheet.composeapp.generated.resources.character_sheet__skills__title import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__title import lwacharactersheet.composeapp.generated.resources.ic_d20_32dp +import lwacharactersheet.composeapp.generated.resources.ic_skull_32dp import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource @@ -124,6 +129,13 @@ fun CharacterSheetPage( CharacterSheetPageContent( modifier = Modifier.fillMaxSize(), characterSheet = sheet, + diminishedValue = viewModel.diminishedValue, + onDiminished = { + blurController.show() + scope.launch { + viewModel.showDiminishedDialog() + } + }, onEdit = { screen.navigateToCharacterSheetEdit( id = sheet.id, @@ -144,7 +156,9 @@ fun CharacterSheetPage( }, onSubCharacteristic = { blurController.show() - viewModel.showSubCharacteristicDialog(id = it.id) + scope.launch { + viewModel.showSubCharacteristicDialog(id = it.id) + } }, onSkill = { node -> blurController.show() @@ -215,6 +229,20 @@ fun CharacterSheetPage( viewModel.hideSubCharacteristicDialog() } ) + + DiminishedStatDialog( + dialog = viewModel.diminishedDialog, + onConfirm = { + viewModel.changeDiminished( + dialog = it + ) + viewModel.hideDiminishedDialog() + }, + onDismissRequest = { + blurController.hide() + viewModel.hideDiminishedDialog() + }, + ) } } @@ -223,6 +251,8 @@ fun CharacterSheetPageContent( modifier: Modifier = Modifier, scrollState: ScrollState = rememberScrollState(), characterSheet: CharacterSheetPageUio, + diminishedValue: State, + onDiminished: () -> Unit, onEdit: () -> Unit, onDelete: () -> Unit, onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit, @@ -243,6 +273,35 @@ fun CharacterSheetPageContent( ) }, actions = { + Box { + IconButton( + onClick = onDiminished, + ) { + Icon( + modifier = Modifier.size(size = 24.dp), + painter = painterResource(Res.drawable.ic_skull_32dp), + tint = MaterialTheme.colors.primary, + contentDescription = null, + ) + } + AnimatedContent( + modifier = Modifier.align(alignment = Alignment.BottomCenter), + targetState = diminishedValue.value, + transitionSpec = { + val sign = if ((targetState ?: 0) > (initialState ?: 0)) 1 else -1 + val enter = fadeIn() + slideInVertically { 16 * sign } + val exit = fadeOut() + slideOutVertically { -16 * sign } + enter togetherWith exit using SizeTransform(clip = false) + } + ) { + Text( + style = MaterialTheme.typography.caption, + color = MaterialTheme.colors.onSurface, + text = "${it ?: ""}", + ) + } + } + IconButton( onClick = onEdit, ) { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt index 53609c9..5342bf0 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt @@ -8,12 +8,22 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetDestination import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialogUio +import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.DiminishedStatDialogUio import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.StatChangeDialogUio import com.pixelized.desktop.lwa.utils.extention.collectAsState +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.runBlocking +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.character_sheet__diminished__label +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__hit_point +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__sub_characteristics__power_point +import org.jetbrains.compose.resources.getString import kotlin.math.max import kotlin.math.min @@ -36,16 +46,36 @@ class CharacterSheetViewModel( private val _statChangeDialog = mutableStateOf(null) val statChangeDialog: State get() = _statChangeDialog - val sheet: State + private val _diminishedDialog = mutableStateOf(null) + val diminishedDialog: State get() = _diminishedDialog + + val diminishedValue: State @Composable @Stable get() = repository - .characterSheetFlow(id = argument.id) - .collectAsState { sheet -> - sheet?.let { model -> - runBlocking { factory.convertToUio(model = model) } - } + .characterDiminishedFlow(id = argument.id) + .collectAsState { it -> it.takeIf { it > 0 } } + + val sheet: State + @Composable + @Stable + get() = combine( + repository.characterSheetFlow(id = argument.id), + repository.characterDiminishedFlow(id = argument.id), + transform = { sheet, diminished -> sheet to diminished }, + ).stateIn( + scope = viewModelScope, + started = SharingStarted.Lazily, + initialValue = run { + val sheet = repository.characterSheetFlow(id = argument.id).value + val diminished = repository.characterDiminishedFlow(id = argument.id).value + sheet to diminished } + ).collectAsState { (sheet, diminished) -> + sheet?.let { model -> + runBlocking { factory.convertToUio(model = model, diminished = diminished) } + } + } fun deleteCharacter(id: String) { repository.delete(id = id) @@ -87,7 +117,7 @@ class CharacterSheetViewModel( _displayDeleteConfirmationDialog.value = null } - fun showSubCharacteristicDialog(id: String) { + suspend fun showSubCharacteristicDialog(id: String) { repository.characterSheetFlow(id = argument.id).value?.let { sheet -> _statChangeDialog.value = when (id) { CharacterSheetFactory.HP -> { @@ -98,9 +128,9 @@ class CharacterSheetViewModel( ) StatChangeDialogUio( id = CharacterSheetFactory.HP, + label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__hit_point), value = { value.value }, onValueChange = { value.value = it }, - placeholder = "${sheet.currentHp}", maxValue = "${sheet.maxHp}", ) } @@ -113,9 +143,9 @@ class CharacterSheetViewModel( ) StatChangeDialogUio( id = CharacterSheetFactory.PP, + label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__power_point), value = { value.value }, onValueChange = { value.value = it }, - placeholder = "${sheet.currentPP}", maxValue = "${sheet.maxPP}", ) } @@ -151,4 +181,32 @@ class CharacterSheetViewModel( fun hideRollOverlay() { _displayRollOverlay.value = false } + + suspend fun showDiminishedDialog() { + val diminished = repository.characterDiminishedFlow(id = argument.id).value + val textFieldValue = + mutableStateOf(TextFieldValue("$diminished", selection = TextRange(index = 0))) + _diminishedDialog.value = DiminishedStatDialogUio( + label = getString(resource = Res.string.character_sheet__diminished__label), + value = { textFieldValue.value }, + onValueChange = { value -> + textFieldValue.value = when (value.text.toIntOrNull()?.takeIf { it >= 0 }) { + null -> TextFieldValue("0", selection = TextRange(index = 0)) + else -> value + } + }, + ) + } + + fun hideDiminishedDialog() { + _diminishedDialog.value = null + } + + fun changeDiminished(dialog: DiminishedStatDialogUio) { + val value = dialog.value().text.toIntOrNull() ?: 0 + repository.setDiminishedForCharacter( + id = argument.id, + diminished = value, + ) + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt index 59b467e..3a346b9 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt @@ -11,17 +11,17 @@ 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.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.material.Text -import androidx.compose.material.TextField import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.Stable @@ -31,17 +31,19 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.composable.decoratedBox.DecoratedBox @Stable data class StatChangeDialogUio( val id: String, + val label: String, val value: () -> TextFieldValue, - val placeholder: String, val onValueChange: (TextFieldValue) -> Unit, val maxValue: String, ) @@ -104,40 +106,49 @@ private fun Dialog( .padding(all = 32.dp), contentAlignment = Alignment.Center, ) { - Surface( - shape = remember { RoundedCornerShape(size = 16.dp) }, - ) { - Row( - modifier = Modifier.padding(all = 16.dp), - horizontalArrangement = Arrangement.spacedBy(4.dp), - ) { - TextField( - modifier = Modifier - .focusRequester(focusRequester = focusRequester) - .alignByBaseline() - .width(width = 120.dp), - value = dialog.value(), - textStyle = remember { - typography.body1.copy( - color = colors.primary, - textAlign = TextAlign.End, - fontWeight = FontWeight.Bold + DecoratedBox { + Surface { + Column( + modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(space = 8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + style = MaterialTheme.typography.caption, + text = dialog.label, + ) + Row( + horizontalArrangement = Arrangement.spacedBy(4.dp), + ) { + BasicTextField( + modifier = Modifier + .focusRequester(focusRequester = focusRequester) + .alignByBaseline() + .width(width = 120.dp), + textStyle = remember { + typography.h5.copy( + color = colors.primary, + textAlign = TextAlign.End, + fontWeight = FontWeight.Bold + ) + }, + cursorBrush = SolidColor(MaterialTheme.colors.primary), + singleLine = true, + keyboardActions = KeyboardActions { onConfirm(dialog) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + value = dialog.value(), + onValueChange = dialog.onValueChange, ) - }, - singleLine = true, - keyboardActions = KeyboardActions { onConfirm(dialog) }, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), - placeholder = { dialog.placeholder }, - onValueChange = dialog.onValueChange, - ) - Text( - modifier = Modifier.alignByBaseline(), - text = "/", - ) - Text( - modifier = Modifier.alignByBaseline(), - text = dialog.maxValue, - ) + Text( + modifier = Modifier.alignByBaseline(), + text = "/", + ) + Text( + modifier = Modifier.alignByBaseline(), + text = dialog.maxValue, + ) + } + } } } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt new file mode 100644 index 0000000..4eacd07 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt @@ -0,0 +1,139 @@ +package com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog + +import androidx.compose.animation.AnimatedContent +import androidx.compose.animation.SizeTransform +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut +import androidx.compose.animation.slideInVertically +import androidx.compose.animation.slideOutVertically +import androidx.compose.animation.togetherWith +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.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.foundation.text.KeyboardActions +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +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.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.SolidColor +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.TextFieldValue +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.composable.decoratedBox.DecoratedBox + +@Stable +data class DiminishedStatDialogUio( + val label: String, + val value: () -> TextFieldValue, + val onValueChange: (TextFieldValue) -> Unit, +) + +@Composable +fun DiminishedStatDialog( + dialog: State, + onConfirm: (DiminishedStatDialogUio) -> Unit, + onDismissRequest: () -> Unit, +) { + AnimatedContent( + modifier = Modifier.fillMaxSize(), + targetState = dialog.value, + transitionSpec = { + val enter = fadeIn() + slideInVertically { 32 } + val exit = fadeOut() + slideOutVertically { 32 } + enter togetherWith exit using SizeTransform(clip = false) + }, + ) { + Box( + modifier = Modifier.fillMaxSize() + ) { + when (it) { + null -> Box( + modifier = Modifier, + ) + + else -> Dialog( + dialog = it, + onConfirm = onConfirm, + onDismissRequest = onDismissRequest, + ) + } + } + } +} + +@Composable +private fun Dialog( + dialog: DiminishedStatDialogUio, + onConfirm: (DiminishedStatDialogUio) -> Unit, + onDismissRequest: () -> Unit, +) { + val typography = MaterialTheme.typography + val colors = MaterialTheme.colors + + val focusRequester = remember { FocusRequester() } + LaunchedEffect(Unit) { + focusRequester.requestFocus() + } + + Box( + modifier = Modifier + .clickable( + interactionSource = remember { MutableInteractionSource() }, + indication = null, + onClick = onDismissRequest, + ) + .fillMaxSize() + .padding(all = 32.dp), + contentAlignment = Alignment.Center, + ) { + DecoratedBox { + Surface { + Column( + modifier = Modifier.padding(vertical = 8.dp, horizontal = 16.dp), + verticalArrangement = Arrangement.spacedBy(space = 8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + Text( + style = MaterialTheme.typography.caption, + text = dialog.label, + ) + BasicTextField( + modifier = Modifier + .focusRequester(focusRequester = focusRequester) + .width(width = 120.dp), + textStyle = remember { + typography.h5.copy( + color = colors.primary, + textAlign = TextAlign.Center, + fontWeight = FontWeight.Bold + ) + }, + cursorBrush = SolidColor(MaterialTheme.colors.primary), + singleLine = true, + keyboardActions = KeyboardActions { onConfirm(dialog) }, + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + value = dialog.value(), + onValueChange = dialog.onValueChange, + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt index 1e36700..069b0fe 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/roll/RollViewModel.kt @@ -31,6 +31,7 @@ import lwacharactersheet.composeapp.generated.resources.roll_page__success import org.jetbrains.compose.resources.getString class RollViewModel : ViewModel() { + private val sheetRepository = CharacterSheetRepository private val repository = RollHistoryRepository private lateinit var sheet: CharacterSheet @@ -54,11 +55,12 @@ class RollViewModel : ViewModel() { sheet: CharacterSheetPageUio, characteristic: CharacterSheetPageUio.Characteristic, ) { + val diminished = sheetRepository.characterDiminishedFlow(id = sheet.id).value prepareRoll( sheet = sheet, label = characteristic.label, rollAction = "1d100", - rollSuccessValue = (characteristic.value.toIntOrNull() ?: 0) * 5, + rollSuccessValue = (characteristic.value.toIntOrNull() ?: 0) * 5 - diminished, ) }