Add PP and HP managmenet
This commit is contained in:
parent
f6d026d50f
commit
3705fbd947
5 changed files with 305 additions and 8 deletions
|
|
@ -4,66 +4,105 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheet
|
||||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic
|
||||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node
|
import com.pixelized.desktop.lwa.screen.characterSheet.detail.CharacterSheetPageUio.Node
|
||||||
import lwacharactersheet.composeapp.generated.resources.Res
|
import lwacharactersheet.composeapp.generated.resources.Res
|
||||||
import lwacharactersheet.composeapp.generated.resources.*
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__cha
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__con
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__dex
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__hei
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__int
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__pow
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__str
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__str
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__armor
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__damage_bonus
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__hit_point
|
||||||
|
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 org.jetbrains.compose.resources.getString
|
||||||
|
|
||||||
class CharacterSheetFactory {
|
class CharacterSheetFactory {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val HP = "HP"
|
||||||
|
const val PP = "PP"
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio {
|
suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio {
|
||||||
return CharacterSheetPageUio(
|
return CharacterSheetPageUio(
|
||||||
id = model.id,
|
id = model.id,
|
||||||
name = model.name,
|
name = model.name,
|
||||||
characteristics = listOf(
|
characteristics = listOf(
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "STR",
|
||||||
label = getString(Res.string.character_sheet__characteristics__str),
|
label = getString(Res.string.character_sheet__characteristics__str),
|
||||||
value = "${model.strength}",
|
value = "${model.strength}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "DEX",
|
||||||
label = getString(Res.string.character_sheet__characteristics__dex),
|
label = getString(Res.string.character_sheet__characteristics__dex),
|
||||||
value = "${model.dexterity}",
|
value = "${model.dexterity}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "CON",
|
||||||
label = getString(Res.string.character_sheet__characteristics__con),
|
label = getString(Res.string.character_sheet__characteristics__con),
|
||||||
value = "${model.constitution}",
|
value = "${model.constitution}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "HEI",
|
||||||
label = getString(Res.string.character_sheet__characteristics__hei),
|
label = getString(Res.string.character_sheet__characteristics__hei),
|
||||||
value = "${model.height}",
|
value = "${model.height}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "INT",
|
||||||
label = getString(Res.string.character_sheet__characteristics__int),
|
label = getString(Res.string.character_sheet__characteristics__int),
|
||||||
value = "${model.intelligence}",
|
value = "${model.intelligence}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "POW",
|
||||||
label = getString(Res.string.character_sheet__characteristics__pow),
|
label = getString(Res.string.character_sheet__characteristics__pow),
|
||||||
value = "${model.power}",
|
value = "${model.power}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "CHA",
|
||||||
label = getString(Res.string.character_sheet__characteristics__cha),
|
label = getString(Res.string.character_sheet__characteristics__cha),
|
||||||
value = "${model.charisma}",
|
value = "${model.charisma}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
subCharacteristics = listOf(
|
subCharacteristics = listOf(
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "MOV",
|
||||||
label = getString(Res.string.character_sheet__sub_characteristics__movement),
|
label = getString(Res.string.character_sheet__sub_characteristics__movement),
|
||||||
value = "${model.movement}",
|
value = "${model.movement}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = HP,
|
||||||
label = getString(Res.string.character_sheet__sub_characteristics__hit_point),
|
label = getString(Res.string.character_sheet__sub_characteristics__hit_point),
|
||||||
value = "${model.currentHp}/${model.maxHp}",
|
value = "${model.currentHp}/${model.maxHp}",
|
||||||
|
editable = true,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = PP,
|
||||||
label = getString(Res.string.character_sheet__sub_characteristics__power_point),
|
label = getString(Res.string.character_sheet__sub_characteristics__power_point),
|
||||||
value = "${model.currentPP}/${model.maxPP}",
|
value = "${model.currentPP}/${model.maxPP}",
|
||||||
|
editable = true,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "DMG",
|
||||||
label = getString(Res.string.character_sheet__sub_characteristics__damage_bonus),
|
label = getString(Res.string.character_sheet__sub_characteristics__damage_bonus),
|
||||||
value = model.damageBonus,
|
value = model.damageBonus,
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
Characteristic(
|
Characteristic(
|
||||||
|
id = "ARMOR",
|
||||||
label = getString(Res.string.character_sheet__sub_characteristics__armor),
|
label = getString(Res.string.character_sheet__sub_characteristics__armor),
|
||||||
value = "${model.armor}",
|
value = "${model.armor}",
|
||||||
|
editable = false,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
skills = model.skills.mapNotNull {
|
skills = model.skills.mapNotNull {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,8 @@ import com.pixelized.desktop.lwa.composable.overlay.BlurOverlay
|
||||||
import com.pixelized.desktop.lwa.composable.overlay.BlurOverlayViewModel
|
import com.pixelized.desktop.lwa.composable.overlay.BlurOverlayViewModel
|
||||||
import com.pixelized.desktop.lwa.navigation.LocalScreenController
|
import com.pixelized.desktop.lwa.navigation.LocalScreenController
|
||||||
import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheetEdit
|
import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheetEdit
|
||||||
|
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.roll.RollPage
|
import com.pixelized.desktop.lwa.screen.roll.RollPage
|
||||||
import com.pixelized.desktop.lwa.screen.roll.RollViewModel
|
import com.pixelized.desktop.lwa.screen.roll.RollViewModel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
@ -70,8 +72,10 @@ data class CharacterSheetPageUio(
|
||||||
) {
|
) {
|
||||||
@Stable
|
@Stable
|
||||||
data class Characteristic(
|
data class Characteristic(
|
||||||
|
val id: String,
|
||||||
val label: String,
|
val label: String,
|
||||||
val value: String,
|
val value: String,
|
||||||
|
val editable: Boolean,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
@ -132,6 +136,9 @@ fun CharacterSheetPage(
|
||||||
)
|
)
|
||||||
overlayViewModel.show()
|
overlayViewModel.show()
|
||||||
},
|
},
|
||||||
|
onSubCharacteristic = {
|
||||||
|
viewModel.showSubCharacteristicDialog(id = it.id)
|
||||||
|
},
|
||||||
onSkill = { node ->
|
onSkill = { node ->
|
||||||
rollViewModel.prepareRoll(sheet = sheet, node = node)
|
rollViewModel.prepareRoll(sheet = sheet, node = node)
|
||||||
overlayViewModel.show()
|
overlayViewModel.show()
|
||||||
|
|
@ -161,6 +168,20 @@ fun CharacterSheetPage(
|
||||||
viewModel.hideConfirmCharacterDeletionDialog()
|
viewModel.hideConfirmCharacterDeletionDialog()
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
CharacterSheetStatDialog(
|
||||||
|
dialog = viewModel.statChangeDialog,
|
||||||
|
onConfirm = {
|
||||||
|
viewModel.changeSubCharacteristic(
|
||||||
|
characteristicId = it.id,
|
||||||
|
value = it.value().text.toIntOrNull() ?: 0,
|
||||||
|
)
|
||||||
|
viewModel.hideSubCharacteristicDialog()
|
||||||
|
},
|
||||||
|
onDismissRequest = {
|
||||||
|
viewModel.hideSubCharacteristicDialog()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
@ -171,6 +192,7 @@ fun CharacterSheetPageContent(
|
||||||
onEdit: () -> Unit,
|
onEdit: () -> Unit,
|
||||||
onDelete: () -> Unit,
|
onDelete: () -> Unit,
|
||||||
onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
||||||
|
onSubCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
||||||
onSkill: (skill: CharacterSheetPageUio.Node) -> Unit,
|
onSkill: (skill: CharacterSheetPageUio.Node) -> Unit,
|
||||||
onUseSkill: (skill: CharacterSheetPageUio.Node) -> Unit,
|
onUseSkill: (skill: CharacterSheetPageUio.Node) -> Unit,
|
||||||
onRoll: (roll: CharacterSheetPageUio.Roll) -> Unit,
|
onRoll: (roll: CharacterSheetPageUio.Roll) -> Unit,
|
||||||
|
|
@ -252,9 +274,13 @@ fun CharacterSheetPageContent(
|
||||||
text = stringResource(Res.string.character_sheet__sub_characteristics__title),
|
text = stringResource(Res.string.character_sheet__sub_characteristics__title),
|
||||||
)
|
)
|
||||||
characterSheet.subCharacteristics.forEach {
|
characterSheet.subCharacteristics.forEach {
|
||||||
Characteristics(
|
SubCharacteristics(
|
||||||
modifier = Modifier.cell(),
|
modifier = Modifier.cell(),
|
||||||
characteristic = it,
|
characteristic = it,
|
||||||
|
onCharacteristic = when {
|
||||||
|
it.editable -> onSubCharacteristic
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -372,24 +398,32 @@ private fun Stat(
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun Characteristics(
|
private fun SubCharacteristics(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
paddingValues: PaddingValues = PaddingValues(horizontal = 8.dp),
|
paddingValues: PaddingValues = PaddingValues(horizontal = 8.dp),
|
||||||
characteristic: CharacterSheetPageUio.Characteristic,
|
characteristic: CharacterSheetPageUio.Characteristic,
|
||||||
|
onCharacteristic: ((characteristic: CharacterSheetPageUio.Characteristic) -> Unit)?,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.padding(paddingValues = paddingValues).then(other = modifier),
|
modifier = Modifier
|
||||||
|
.clickable(enabled = characteristic.editable && onCharacteristic != null) {
|
||||||
|
onCharacteristic?.invoke(characteristic)
|
||||||
|
}
|
||||||
|
.padding(paddingValues = paddingValues).then(other = modifier),
|
||||||
horizontalArrangement = Arrangement.SpaceBetween,
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.alignByBaseline(),
|
|
||||||
style = MaterialTheme.typography.body1,
|
style = MaterialTheme.typography.body1,
|
||||||
text = characteristic.label
|
text = characteristic.label
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.alignByBaseline(),
|
|
||||||
style = MaterialTheme.typography.body1,
|
style = MaterialTheme.typography.body1,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
|
color = when (characteristic.editable && onCharacteristic != null) {
|
||||||
|
true -> MaterialTheme.colors.primary
|
||||||
|
else -> MaterialTheme.colors.onSurface
|
||||||
|
},
|
||||||
text = characteristic.value,
|
text = characteristic.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,18 @@ import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.ui.text.TextRange
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination
|
import com.pixelized.desktop.lwa.navigation.destination.CharacterSheetDestination
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
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.StatChangeDialogUio
|
||||||
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
|
|
||||||
class CharacterSheetViewModel(
|
class CharacterSheetViewModel(
|
||||||
savedStateHandle: SavedStateHandle,
|
savedStateHandle: SavedStateHandle,
|
||||||
|
|
@ -24,6 +30,9 @@ class CharacterSheetViewModel(
|
||||||
val displayDeleteConfirmationDialog: State<CharacterSheetDeleteConfirmationDialogUio?>
|
val displayDeleteConfirmationDialog: State<CharacterSheetDeleteConfirmationDialogUio?>
|
||||||
get() = _displayDeleteConfirmationDialog
|
get() = _displayDeleteConfirmationDialog
|
||||||
|
|
||||||
|
private val _statChangeDialog = mutableStateOf<StatChangeDialogUio?>(null)
|
||||||
|
val statChangeDialog: State<StatChangeDialogUio?> get() = _statChangeDialog
|
||||||
|
|
||||||
val sheet: State<CharacterSheetPageUio?>
|
val sheet: State<CharacterSheetPageUio?>
|
||||||
@Composable
|
@Composable
|
||||||
@Stable
|
@Stable
|
||||||
|
|
@ -35,7 +44,7 @@ class CharacterSheetViewModel(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteCharacter(id: String) {
|
fun deleteCharacter(id: String) {
|
||||||
repository.delete(id = id)
|
repository.delete(id = id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,4 +83,61 @@ class CharacterSheetViewModel(
|
||||||
fun hideConfirmCharacterDeletionDialog() {
|
fun hideConfirmCharacterDeletionDialog() {
|
||||||
_displayDeleteConfirmationDialog.value = null
|
_displayDeleteConfirmationDialog.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showSubCharacteristicDialog(id: String) {
|
||||||
|
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||||
|
_statChangeDialog.value = when (id) {
|
||||||
|
CharacterSheetFactory.HP -> {
|
||||||
|
val value = mutableStateOf(
|
||||||
|
"${sheet.currentHp}".let {
|
||||||
|
TextFieldValue(text = it, selection = TextRange(it.length))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
StatChangeDialogUio(
|
||||||
|
id = CharacterSheetFactory.HP,
|
||||||
|
value = { value.value },
|
||||||
|
onValueChange = { value.value = it },
|
||||||
|
placeholder = "${sheet.currentHp}",
|
||||||
|
maxValue = "${sheet.maxHp}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
CharacterSheetFactory.PP -> {
|
||||||
|
val value = mutableStateOf(
|
||||||
|
"${sheet.currentPP}".let {
|
||||||
|
TextFieldValue(text = it, selection = TextRange(it.length))
|
||||||
|
}
|
||||||
|
)
|
||||||
|
StatChangeDialogUio(
|
||||||
|
id = CharacterSheetFactory.PP,
|
||||||
|
value = { value.value },
|
||||||
|
onValueChange = { value.value = it },
|
||||||
|
placeholder = "${sheet.currentPP}",
|
||||||
|
maxValue = "${sheet.maxPP}",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun hideSubCharacteristicDialog() {
|
||||||
|
_statChangeDialog.value = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun changeSubCharacteristic(
|
||||||
|
characteristicId: String,
|
||||||
|
value: Int,
|
||||||
|
) {
|
||||||
|
val sheet = repository.characterSheetFlow(id = argument.id).value
|
||||||
|
val updated = when (characteristicId) {
|
||||||
|
CharacterSheetFactory.HP -> sheet?.copy(currentHp = max(0, min(sheet.maxHp, value)))
|
||||||
|
CharacterSheetFactory.PP -> sheet?.copy(currentPP = max(0, min(sheet.maxPP, value)))
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
updated?.let {
|
||||||
|
repository.save(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package com.pixelized.desktop.lwa.screen.characterSheet.detail
|
package com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
package com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
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.background
|
||||||
|
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.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.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
|
||||||
|
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.Color
|
||||||
|
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
|
||||||
|
|
||||||
|
private val DefaultScrimColor = Color.Black.copy(alpha = 0.6f)
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
data class StatChangeDialogUio(
|
||||||
|
val id: String,
|
||||||
|
val value: () -> TextFieldValue,
|
||||||
|
val placeholder: String,
|
||||||
|
val onValueChange: (TextFieldValue) -> Unit,
|
||||||
|
val maxValue: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun CharacterSheetStatDialog(
|
||||||
|
dialog: State<StatChangeDialogUio?>,
|
||||||
|
onConfirm: (StatChangeDialogUio) -> Unit,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = dialog.value != null,
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.background(color = DefaultScrimColor),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
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: StatChangeDialogUio,
|
||||||
|
onConfirm: (StatChangeDialogUio) -> 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,
|
||||||
|
) {
|
||||||
|
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
|
||||||
|
)
|
||||||
|
},
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue