Add diminished status management.
This commit is contained in:
parent
59f8aff121
commit
e880d37275
10 changed files with 371 additions and 51 deletions
|
|
@ -1,3 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="512"
|
||||
android:viewportHeight="512">
|
||||
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M437.914,74.078C392.43,27,326.117,0,255.992,0C185.883,0,119.57,27,74.102,74.063 c-42.5,44-64.703,102.828-62.531,165.688l6.609,83.875c6.031,84.75,55.234,93.906,76.094,93.906c7.563,0,15.531-1.094,23.625-3.188 c1.094,7.938,1,21.859,0.922,32.688l-0.078,15.063c-0.141,10.938-0.359,27.5,11.234,39.234c4.797,4.875,13.563,10.672,28,10.672 h196.047c14.438,0,23.188-5.797,28-10.656c11.578-11.75,11.375-28.297,11.234-39.25l-0.094-15.031 c-0.063-10.844-0.172-24.781,0.938-32.719c8.172,2.109,16.094,3.188,23.625,3.188c20.859,0,70.047-9.156,76.094-93.75l6.563-83.156 l0.047-0.875C502.602,176.891,480.398,118.063,437.914,74.078z M459.961,237.906l-6.516,82.844 c-2.672,37.344-14.703,56.281-35.719,56.281c-4.844,0-10.266-0.891-16.297-2.688c-14.406-4.156-26.891-1.375-35.703,7.5 c-13.406,13.5-13.266,35.313-13.047,65.5l0.078,15.281c0.031,2.5,0.078,6.188-0.141,8.875h-42.75v-50.016h-32.406V471.5h-42.938 v-50.016h-32.391V471.5h-42.766c-0.203-2.688-0.156-6.375-0.125-8.906l0.078-15.297c0.219-30.156,0.359-51.953-13.047-65.453 c-8.766-8.844-20.953-11.75-35.875-7.453c-5.859,1.75-11.281,2.641-16.125,2.641c-21.031,0-33.031-18.938-35.719-56.438 l-6.531-82.688c-1.656-51.609,16.5-99.781,51.203-135.688C141.117,63,196.805,40.5,255.992,40.5 c59.203,0,114.891,22.5,152.781,61.719C443.477,138.125,461.648,186.297,459.961,237.906z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M256.008,309.656c-9.719,0-31.125,46.688-35.031,54.469c-3.875,7.781,3.906,19.469,15.578,15.563 c11.672-3.875,19.453-13.609,19.453-13.609s7.781,9.734,19.453,13.609c11.656,3.906,19.453-7.781,15.563-15.563 C287.117,356.344,265.742,309.656,256.008,309.656z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M171.586,183.281c-30.891-3.25-58.578,19.188-61.828,50.094l-4.188,29.422 c-3.25,30.922,19.188,58.578,50.078,61.828c30.922,3.25,58.609-19.172,61.844-50.094l4.188-29.422 C224.914,214.188,202.508,186.531,171.586,183.281z" />
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M402.242,233.375c-3.234-30.906-30.938-53.344-61.828-50.094c-30.922,3.25-53.328,30.906-50.094,61.828 l4.172,29.422c3.25,30.922,30.938,53.344,61.844,50.094s53.344-30.906,50.094-61.828L402.242,233.375z" />
|
||||
</vector>
|
||||
|
|
@ -58,6 +58,7 @@
|
|||
<string name="character_sheet_edit__magic__title">Compétences magiques</string>
|
||||
<string name="character_sheet_edit__magic__add_action">Ajouter une compétence magique</string>
|
||||
|
||||
<string name="character_sheet__diminished__label">État diminuer</string>
|
||||
<string name="character_sheet__characteristics__str">Force</string>
|
||||
<string name="character_sheet__characteristics__dex">Dextérité</string>
|
||||
<string name="character_sheet__characteristics__con">Constitution</string>
|
||||
|
|
|
|||
|
|
@ -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<Map<String, Int>>(emptyMap())
|
||||
|
||||
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> {
|
||||
return sheets
|
||||
}
|
||||
|
|
@ -34,6 +37,18 @@ object CharacterSheetRepository {
|
|||
)
|
||||
}
|
||||
|
||||
fun characterDiminishedFlow(id: String?): StateFlow<Int> {
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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<Int?>,
|
||||
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,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -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<StatChangeDialogUio?>(null)
|
||||
val statChangeDialog: State<StatChangeDialogUio?> get() = _statChangeDialog
|
||||
|
||||
val sheet: State<CharacterSheetPageUio?>
|
||||
private val _diminishedDialog = mutableStateOf<DiminishedStatDialogUio?>(null)
|
||||
val diminishedDialog: State<DiminishedStatDialogUio?> get() = _diminishedDialog
|
||||
|
||||
val diminishedValue: State<Int?>
|
||||
@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<CharacterSheetPageUio?>
|
||||
@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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<DiminishedStatDialogUio?>,
|
||||
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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue