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"
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:width="32dp"
|
android:width="32dp"
|
||||||
android:height="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__title">Compétences magiques</string>
|
||||||
<string name="character_sheet_edit__magic__add_action">Ajouter une compétence magique</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__str">Force</string>
|
||||||
<string name="character_sheet__characteristics__dex">Dextérité</string>
|
<string name="character_sheet__characteristics__dex">Dextérité</string>
|
||||||
<string name="character_sheet__characteristics__con">Constitution</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.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
|
@ -18,6 +19,8 @@ object CharacterSheetRepository {
|
||||||
initialValue = emptyList()
|
initialValue = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val diminished = MutableStateFlow<Map<String, Int>>(emptyMap())
|
||||||
|
|
||||||
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> {
|
fun characterSheetFlow(): StateFlow<List<CharacterSheet>> {
|
||||||
return sheets
|
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) {
|
fun save(characterSheet: CharacterSheet) {
|
||||||
val savedSheets = store.load().toMutableList()
|
val savedSheets = store.load().toMutableList()
|
||||||
val savedIndex = savedSheets.indexOfFirst { it.id == characterSheet.id }
|
val savedIndex = savedSheets.indexOfFirst { it.id == characterSheet.id }
|
||||||
|
|
@ -53,5 +68,11 @@ object CharacterSheetRepository {
|
||||||
savedSheets.removeIf { it.id == id }
|
savedSheets.removeIf { it.id == id }
|
||||||
store.save(sheets = savedSheets)
|
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__movement
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
|
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__power_point
|
||||||
import org.jetbrains.compose.resources.getString
|
import org.jetbrains.compose.resources.getString
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
class CharacterSheetFactory {
|
class CharacterSheetFactory {
|
||||||
|
|
||||||
|
|
@ -25,7 +26,10 @@ class CharacterSheetFactory {
|
||||||
const val PP = "PP"
|
const val PP = "PP"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun convertToUio(model: CharacterSheet): CharacterSheetPageUio {
|
suspend fun convertToUio(
|
||||||
|
model: CharacterSheet,
|
||||||
|
diminished: Int,
|
||||||
|
): CharacterSheetPageUio {
|
||||||
return CharacterSheetPageUio(
|
return CharacterSheetPageUio(
|
||||||
id = model.id,
|
id = model.id,
|
||||||
name = model.name,
|
name = model.name,
|
||||||
|
|
@ -109,7 +113,7 @@ class CharacterSheetFactory {
|
||||||
if (it.value > 0) {
|
if (it.value > 0) {
|
||||||
Node(
|
Node(
|
||||||
label = it.label,
|
label = it.label,
|
||||||
value = it.value,
|
value = it.value.diminished(diminished),
|
||||||
used = it.used,
|
used = it.used,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -120,7 +124,7 @@ class CharacterSheetFactory {
|
||||||
if (it.value > 0) {
|
if (it.value > 0) {
|
||||||
Node(
|
Node(
|
||||||
label = it.label,
|
label = it.label,
|
||||||
value = it.value,
|
value = it.value.diminished(diminished),
|
||||||
used = it.used,
|
used = it.used,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -131,7 +135,7 @@ class CharacterSheetFactory {
|
||||||
if (it.value > 0) {
|
if (it.value > 0) {
|
||||||
Node(
|
Node(
|
||||||
label = it.label,
|
label = it.label,
|
||||||
value = it.value,
|
value = it.value.diminished(diminished),
|
||||||
used = it.used,
|
used = it.used,
|
||||||
)
|
)
|
||||||
} else {
|
} 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
|
package com.pixelized.desktop.lwa.screen.characterSheet.detail
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.SizeTransform
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
import androidx.compose.animation.fadeOut
|
import androidx.compose.animation.fadeOut
|
||||||
import androidx.compose.animation.slideInVertically
|
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.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
import androidx.compose.foundation.layout.PaddingValues
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
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.material.icons.filled.Edit
|
||||||
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.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.ui.Alignment
|
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.navigation.window.LocalWindow
|
||||||
import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialog
|
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.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.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
|
||||||
|
|
@ -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__skills__title
|
||||||
import lwacharactersheet.composeapp.generated.resources.character_sheet__sub_characteristics__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_d20_32dp
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.ic_skull_32dp
|
||||||
import org.jetbrains.compose.resources.painterResource
|
import org.jetbrains.compose.resources.painterResource
|
||||||
import org.jetbrains.compose.resources.stringResource
|
import org.jetbrains.compose.resources.stringResource
|
||||||
|
|
||||||
|
|
@ -124,6 +129,13 @@ fun CharacterSheetPage(
|
||||||
CharacterSheetPageContent(
|
CharacterSheetPageContent(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
characterSheet = sheet,
|
characterSheet = sheet,
|
||||||
|
diminishedValue = viewModel.diminishedValue,
|
||||||
|
onDiminished = {
|
||||||
|
blurController.show()
|
||||||
|
scope.launch {
|
||||||
|
viewModel.showDiminishedDialog()
|
||||||
|
}
|
||||||
|
},
|
||||||
onEdit = {
|
onEdit = {
|
||||||
screen.navigateToCharacterSheetEdit(
|
screen.navigateToCharacterSheetEdit(
|
||||||
id = sheet.id,
|
id = sheet.id,
|
||||||
|
|
@ -144,7 +156,9 @@ fun CharacterSheetPage(
|
||||||
},
|
},
|
||||||
onSubCharacteristic = {
|
onSubCharacteristic = {
|
||||||
blurController.show()
|
blurController.show()
|
||||||
|
scope.launch {
|
||||||
viewModel.showSubCharacteristicDialog(id = it.id)
|
viewModel.showSubCharacteristicDialog(id = it.id)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onSkill = { node ->
|
onSkill = { node ->
|
||||||
blurController.show()
|
blurController.show()
|
||||||
|
|
@ -215,6 +229,20 @@ fun CharacterSheetPage(
|
||||||
viewModel.hideSubCharacteristicDialog()
|
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,
|
modifier: Modifier = Modifier,
|
||||||
scrollState: ScrollState = rememberScrollState(),
|
scrollState: ScrollState = rememberScrollState(),
|
||||||
characterSheet: CharacterSheetPageUio,
|
characterSheet: CharacterSheetPageUio,
|
||||||
|
diminishedValue: State<Int?>,
|
||||||
|
onDiminished: () -> Unit,
|
||||||
onEdit: () -> Unit,
|
onEdit: () -> Unit,
|
||||||
onDelete: () -> Unit,
|
onDelete: () -> Unit,
|
||||||
onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
onCharacteristic: (characteristic: CharacterSheetPageUio.Characteristic) -> Unit,
|
||||||
|
|
@ -243,6 +273,35 @@ fun CharacterSheetPageContent(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
actions = {
|
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(
|
IconButton(
|
||||||
onClick = onEdit,
|
onClick = onEdit,
|
||||||
) {
|
) {
|
||||||
|
|
|
||||||
|
|
@ -8,12 +8,22 @@ import androidx.compose.ui.text.TextRange
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.lifecycle.SavedStateHandle
|
import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetDestination
|
import com.pixelized.desktop.lwa.navigation.screen.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.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.screen.characterSheet.detail.dialog.StatChangeDialogUio
|
||||||
import com.pixelized.desktop.lwa.utils.extention.collectAsState
|
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 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.max
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
|
|
@ -36,14 +46,34 @@ class CharacterSheetViewModel(
|
||||||
private val _statChangeDialog = mutableStateOf<StatChangeDialogUio?>(null)
|
private val _statChangeDialog = mutableStateOf<StatChangeDialogUio?>(null)
|
||||||
val statChangeDialog: State<StatChangeDialogUio?> get() = _statChangeDialog
|
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
|
@Composable
|
||||||
@Stable
|
@Stable
|
||||||
get() = repository
|
get() = repository
|
||||||
.characterSheetFlow(id = argument.id)
|
.characterDiminishedFlow(id = argument.id)
|
||||||
.collectAsState { sheet ->
|
.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 ->
|
sheet?.let { model ->
|
||||||
runBlocking { factory.convertToUio(model = model) }
|
runBlocking { factory.convertToUio(model = model, diminished = diminished) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -87,7 +117,7 @@ class CharacterSheetViewModel(
|
||||||
_displayDeleteConfirmationDialog.value = null
|
_displayDeleteConfirmationDialog.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showSubCharacteristicDialog(id: String) {
|
suspend fun showSubCharacteristicDialog(id: String) {
|
||||||
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
repository.characterSheetFlow(id = argument.id).value?.let { sheet ->
|
||||||
_statChangeDialog.value = when (id) {
|
_statChangeDialog.value = when (id) {
|
||||||
CharacterSheetFactory.HP -> {
|
CharacterSheetFactory.HP -> {
|
||||||
|
|
@ -98,9 +128,9 @@ class CharacterSheetViewModel(
|
||||||
)
|
)
|
||||||
StatChangeDialogUio(
|
StatChangeDialogUio(
|
||||||
id = CharacterSheetFactory.HP,
|
id = CharacterSheetFactory.HP,
|
||||||
|
label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__hit_point),
|
||||||
value = { value.value },
|
value = { value.value },
|
||||||
onValueChange = { value.value = it },
|
onValueChange = { value.value = it },
|
||||||
placeholder = "${sheet.currentHp}",
|
|
||||||
maxValue = "${sheet.maxHp}",
|
maxValue = "${sheet.maxHp}",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -113,9 +143,9 @@ class CharacterSheetViewModel(
|
||||||
)
|
)
|
||||||
StatChangeDialogUio(
|
StatChangeDialogUio(
|
||||||
id = CharacterSheetFactory.PP,
|
id = CharacterSheetFactory.PP,
|
||||||
|
label = getString(resource = Res.string.character_sheet_edit__sub_characteristics__power_point),
|
||||||
value = { value.value },
|
value = { value.value },
|
||||||
onValueChange = { value.value = it },
|
onValueChange = { value.value = it },
|
||||||
placeholder = "${sheet.currentPP}",
|
|
||||||
maxValue = "${sheet.maxPP}",
|
maxValue = "${sheet.maxPP}",
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -151,4 +181,32 @@ class CharacterSheetViewModel(
|
||||||
fun hideRollOverlay() {
|
fun hideRollOverlay() {
|
||||||
_displayRollOverlay.value = false
|
_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.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.width
|
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.KeyboardActions
|
||||||
import androidx.compose.foundation.text.KeyboardOptions
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
import androidx.compose.material.MaterialTheme
|
import androidx.compose.material.MaterialTheme
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.material.Text
|
import androidx.compose.material.Text
|
||||||
import androidx.compose.material.TextField
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
|
|
@ -31,17 +31,19 @@ import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
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.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.ImeAction
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
import androidx.compose.ui.text.input.TextFieldValue
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.text.style.TextAlign
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.pixelized.desktop.lwa.composable.decoratedBox.DecoratedBox
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class StatChangeDialogUio(
|
data class StatChangeDialogUio(
|
||||||
val id: String,
|
val id: String,
|
||||||
|
val label: String,
|
||||||
val value: () -> TextFieldValue,
|
val value: () -> TextFieldValue,
|
||||||
val placeholder: String,
|
|
||||||
val onValueChange: (TextFieldValue) -> Unit,
|
val onValueChange: (TextFieldValue) -> Unit,
|
||||||
val maxValue: String,
|
val maxValue: String,
|
||||||
)
|
)
|
||||||
|
|
@ -104,30 +106,37 @@ private fun Dialog(
|
||||||
.padding(all = 32.dp),
|
.padding(all = 32.dp),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
Surface(
|
DecoratedBox {
|
||||||
shape = remember { RoundedCornerShape(size = 16.dp) },
|
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(
|
Row(
|
||||||
modifier = Modifier.padding(all = 16.dp),
|
|
||||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
) {
|
) {
|
||||||
TextField(
|
BasicTextField(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.focusRequester(focusRequester = focusRequester)
|
.focusRequester(focusRequester = focusRequester)
|
||||||
.alignByBaseline()
|
.alignByBaseline()
|
||||||
.width(width = 120.dp),
|
.width(width = 120.dp),
|
||||||
value = dialog.value(),
|
|
||||||
textStyle = remember {
|
textStyle = remember {
|
||||||
typography.body1.copy(
|
typography.h5.copy(
|
||||||
color = colors.primary,
|
color = colors.primary,
|
||||||
textAlign = TextAlign.End,
|
textAlign = TextAlign.End,
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
cursorBrush = SolidColor(MaterialTheme.colors.primary),
|
||||||
singleLine = true,
|
singleLine = true,
|
||||||
keyboardActions = KeyboardActions { onConfirm(dialog) },
|
keyboardActions = KeyboardActions { onConfirm(dialog) },
|
||||||
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
|
||||||
placeholder = { dialog.placeholder },
|
value = dialog.value(),
|
||||||
onValueChange = dialog.onValueChange,
|
onValueChange = dialog.onValueChange,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -142,3 +151,5 @@ private fun Dialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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
|
import org.jetbrains.compose.resources.getString
|
||||||
|
|
||||||
class RollViewModel : ViewModel() {
|
class RollViewModel : ViewModel() {
|
||||||
|
private val sheetRepository = CharacterSheetRepository
|
||||||
private val repository = RollHistoryRepository
|
private val repository = RollHistoryRepository
|
||||||
|
|
||||||
private lateinit var sheet: CharacterSheet
|
private lateinit var sheet: CharacterSheet
|
||||||
|
|
@ -54,11 +55,12 @@ class RollViewModel : ViewModel() {
|
||||||
sheet: CharacterSheetPageUio,
|
sheet: CharacterSheetPageUio,
|
||||||
characteristic: CharacterSheetPageUio.Characteristic,
|
characteristic: CharacterSheetPageUio.Characteristic,
|
||||||
) {
|
) {
|
||||||
|
val diminished = sheetRepository.characterDiminishedFlow(id = sheet.id).value
|
||||||
prepareRoll(
|
prepareRoll(
|
||||||
sheet = sheet,
|
sheet = sheet,
|
||||||
label = characteristic.label,
|
label = characteristic.label,
|
||||||
rollAction = "1d100",
|
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