From 2f6d0b3819d213b81f070129bc0c8d3d6cde5b57 Mon Sep 17 00:00:00 2001 From: "Andres Gomez, Thomas (ITDV RL)" Date: Thu, 3 Apr 2025 13:41:45 +0200 Subject: [PATCH] Add dynamic alteration inapp management. --- .../com/pixelized/desktop/lwa/Module.kt | 12 +- .../desktop/lwa/network/LwaClient.kt | 2 +- .../desktop/lwa/network/LwaClientImpl.kt | 2 +- .../CharacterSheetRepository.kt | 14 +- .../characterSheet/CharacterSheetStore.kt | 20 ++- .../alterteration/AlterationToggleItem.kt | 84 ++++++++++ .../CharacterSheetAlterationDialog.kt | 154 ++++++++++++++++++ .../CharacterSheetAlterationDialogFactory.kt | 61 +++++++ ...CharacterSheetAlterationDialogViewModel.kt | 121 ++++++++++++++ ...cterSheetCharacteristicDialogViewModel.kt} | 6 +- .../CharacterSheetDiminishedDialog.kt} | 18 +- .../CharacterSheetDiminishedDialogFactory.kt | 5 +- ...haracterSheetDiminishedDialogViewModel.kt} | 9 +- .../ui/composable/textfield/LwaTextField.kt | 10 +- .../lwa/ui/overlay/roll/RollOverlay.kt | 2 +- .../lwa/ui/screen/campaign/CampaignScreen.kt | 46 +++++- .../campaign/player/detail/CharacterDetail.kt | 20 ++- .../player/detail/CharacterDetailFactory.kt | 3 + .../player/detail/CharacterDetailViewModel.kt | 6 +- .../detail/header/CharacterDetailHeader.kt | 21 ++- .../detail/CharacterSheetPage.kt | 8 +- .../detail/CharacterSheetViewModel.kt | 6 +- .../edit/CharacterSheetEditFactory.kt | 8 +- .../edit/CharacterSheetEditViewModel.kt | 6 +- .../edit/GMAlterationEditFactory.kt | 20 +-- .../alteration/edit/GMAlterationEditPage.kt | 2 +- .../alteration/list/GMAlterationViewModel.kt | 4 +- .../character/list/GMCharacterPage.kt | 35 +++- .../character/list/GMCharacterViewModel.kt | 5 +- .../gamemaster/common/GMFilterHeader.kt | 3 + .../gamemaster/common/tag/GMTagFactory.kt | 7 +- .../lwa/ui/screen/levelup/LevelScreen.kt | 2 +- .../lwa/ui/screen/settings/SettingsScreen.kt | 2 +- .../color/component/LwaTextFieldColors.kt | 12 ++ 34 files changed, 639 insertions(+), 97 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/AlterationToggleItem.kt create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialog.kt create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogFactory.kt create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogViewModel.kt rename composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/{CharacterDetailCharacteristicDialogViewModel.kt => CharacterSheetCharacteristicDialogViewModel.kt} (91%) rename composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/{screen/characterSheet/detail/dialog/DiminishedStatDialog.kt => composable/character/diminished/CharacterSheetDiminishedDialog.kt} (92%) rename composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/{CharacterSheetDiminishedViewModel.kt => CharacterSheetDiminishedDialogViewModel.kt} (78%) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt index 4c03877..46b820b 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt @@ -15,10 +15,12 @@ import com.pixelized.desktop.lwa.repository.settings.SettingsRepository import com.pixelized.desktop.lwa.repository.settings.SettingsStore import com.pixelized.desktop.lwa.repository.tag.TagRepository import com.pixelized.desktop.lwa.repository.tag.TagStore -import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogFactory +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogFactory import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogFactory -import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedViewModel +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlayViewModel import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.network.NetworkFactory @@ -128,6 +130,7 @@ val factoryDependencies factoryOf(::CharacterDetailFactory) factoryOf(::CharacterSheetCharacteristicDialogFactory) factoryOf(::CharacterSheetDiminishedDialogFactory) + factoryOf(::CharacterSheetAlterationDialogFactory) factoryOf(::TextMessageFactory) factoryOf(::LevelUpFactory) factoryOf(::GMTagFactory) @@ -148,8 +151,9 @@ val viewModelDependencies viewModelOf(::PlayerRibbonViewModel) viewModelOf(::NpcRibbonViewModel) viewModelOf(::CharacterDetailViewModel) - viewModelOf(::CharacterSheetDiminishedViewModel) - viewModelOf(::CharacterDetailCharacteristicDialogViewModel) + viewModelOf(::CharacterSheetDiminishedDialogViewModel) + viewModelOf(::CharacterSheetCharacteristicDialogViewModel) + viewModelOf(::CharacterSheetAlterationDialogViewModel) viewModelOf(::CampaignChatViewModel) viewModelOf(::SettingsViewModel) viewModelOf(::LevelUpViewModel) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt index e3c66b8..bd7dd73 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClient.kt @@ -79,7 +79,7 @@ interface LwaClient { suspend fun putCharacterAlteration( characterSheetId: String, - alterationId: Int, + alterationId: String, active: Boolean, ): APIResponse diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt index cf4bf3a..9eda911 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/network/LwaClientImpl.kt @@ -142,7 +142,7 @@ class LwaClientImpl( @Throws override suspend fun putCharacterAlteration( characterSheetId: String, - alterationId: Int, + alterationId: String, active: Boolean, ) = client .put("$root/character/update/alteration?characterSheetId=$characterSheetId&alterationId=$alterationId&active=$active") 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 beba518..a10d1f2 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 @@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch class CharacterSheetRepository( private val store: CharacterSheetStore, @@ -64,6 +63,19 @@ class CharacterSheetRepository( store.deleteCharacterSheet(characterSheetId = characterSheetId) } + @Throws + suspend fun updateAlteration( + characterSheetId: String, + alterationId: String, + active: Boolean, + ) { + store.putCharacterAlteration( + characterSheetId = characterSheetId, + alterationId = alterationId, + active = active, + ) + } + fun checkCharacterSheetIdValidity( characterSheetId: String, ): Boolean { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt index 1bcedce..86024b8 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt @@ -94,7 +94,7 @@ class CharacterSheetStore( ) { val json = factory.convertToJson(sheet = sheet) val request = client.putCharacter(sheet = json) - if (request.success) { + if (request.success.not()) { LwaClient.error(error = request) } } @@ -104,7 +104,23 @@ class CharacterSheetStore( characterSheetId: String, ) { val request = client.deleteCharacterSheet(characterSheetId = characterSheetId) - if (request.success) { + if (request.success.not()) { + LwaClient.error(error = request) + } + } + + @Throws + suspend fun putCharacterAlteration( + characterSheetId: String, + alterationId: String, + active: Boolean, + ) { + val request = client.putCharacterAlteration( + characterSheetId = characterSheetId, + alterationId = alterationId, + active = active, + ) + if (request.success.not()) { LwaClient.error(error = request) } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/AlterationToggleItem.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/AlterationToggleItem.kt new file mode 100644 index 0000000..0c93876 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/AlterationToggleItem.kt @@ -0,0 +1,84 @@ +package com.pixelized.desktop.lwa.ui.composable.character.alterteration + +import androidx.compose.animation.animateColorAsState +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.IntrinsicSize +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.material.minimumInteractiveComponentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTag +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio +import com.pixelized.desktop.lwa.ui.theme.lwa + +@Stable +data class AlterationToggleItemUio( + val id: String, + val label: String, + val tags: List, + val active: Boolean, +) + +@Stable +object AlterationToggleItemDefault { + val padding = PaddingValues(start = 8.dp) +} + +@Composable +fun AlterationToggleItem( + modifier: Modifier = Modifier, + alteration: AlterationToggleItemUio, + padding: PaddingValues = AlterationToggleItemDefault.padding, + onAlteration: () -> Unit, + onTag: (String) -> Unit, +) { + Row( + modifier = Modifier + .clip(shape = MaterialTheme.lwa.shapes.gameMaster) + .clickable(onClick = onAlteration) + .background(color = MaterialTheme.lwa.colorScheme.elevated.base1dp) + .minimumInteractiveComponentSize() + .padding(paddingValues = padding) + .then(other = modifier), + horizontalArrangement = Arrangement.spacedBy(space = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + val animatedColor = animateColorAsState( + targetValue = when (alteration.active) { + true -> MaterialTheme.lwa.colorScheme.base.secondary + else -> MaterialTheme.lwa.colorScheme.base.onSurface + } + ) + Text( + style = MaterialTheme.lwa.typography.base.body1, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + color = animatedColor.value, + text = alteration.label, + ) + Row( + modifier = Modifier.weight(1f).height(intrinsicSize = IntrinsicSize.Min), + horizontalArrangement = Arrangement.spacedBy(space = 2.dp, alignment = Alignment.End) + ) { + alteration.tags.forEach { tag -> + GMTag( + elevation = 4.dp, + tag = tag, + onTag = { onTag(tag.id) }, + ) + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialog.kt new file mode 100644 index 0000000..cd5a107 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialog.kt @@ -0,0 +1,154 @@ +package com.pixelized.desktop.lwa.ui.composable.character.alterteration + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.Icon +import androidx.compose.material.IconButton +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.minimumInteractiveComponentSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.GMFilterHeader +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio +import com.pixelized.desktop.lwa.ui.theme.lwa +import kotlinx.coroutines.flow.StateFlow +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.ic_close_24dp +import org.jetbrains.compose.resources.painterResource + +@Stable +data class CharacterSheetAlterationDialogUio( + val characterSheetId: String, + val characterName: String, + val filter: LwaTextFieldUio, + val tags: StateFlow>, + val alterations: List, +) + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +fun CharacterSheetAlterationDialog( + dialog: State, + onConfirm: (CharacterSheetAlterationDialogUio) -> Unit, + onTag: (String) -> Unit, + onAlteration: (characterSheetId: String, alterationId: String, active: Boolean) -> Unit, + onDismissRequest: () -> Unit, +) { + dialog.value?.let { + Dialog( + properties = DialogProperties( + usePlatformDefaultWidth = false, + usePlatformInsets = false, + ), + onDismissRequest = onDismissRequest, + content = { + CharacterSheetAlterationContent( + dialog = it, + onConfirm = onConfirm, + onTag = onTag, + onAlteration = onAlteration, + onDismissRequest = onDismissRequest, + ) + } + ) + } +} + +@Composable +fun CharacterSheetAlterationContent( + dialog: CharacterSheetAlterationDialogUio, + onConfirm: (CharacterSheetAlterationDialogUio) -> Unit, + onTag: (String) -> Unit, + onAlteration: (characterSheetId: String, alterationId: String, active: Boolean) -> Unit, + onDismissRequest: () -> Unit, +) { + Surface( + modifier = Modifier + .fillMaxHeight() + .width(width = 128.dp * 4) + .padding(vertical = 16.dp), + ) { + Column( + modifier = Modifier.fillMaxSize(), + ) { + Row( + modifier = Modifier.padding(start = 16.dp).fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.SpaceBetween, + ) { + Text( + style = MaterialTheme.typography.h6, + color = MaterialTheme.colors.onSurface, + text = dialog.characterName, + ) + IconButton( + onClick = onDismissRequest, + ) { + Icon( + painter = painterResource(Res.drawable.ic_close_24dp), + tint = MaterialTheme.lwa.colorScheme.base.primary, + contentDescription = null, + ) + } + } + GMFilterHeader( + filter = dialog.filter, + tags = dialog.tags.collectAsState(), + onTag = onTag, + ) + LazyColumn( + modifier = Modifier + .fillMaxWidth() + .weight(weight = 1f), + contentPadding = PaddingValues(start = 8.dp, end = 8.dp, bottom = 8.dp), + verticalArrangement = Arrangement.spacedBy(space = 8.dp), + ) { + items( + items = dialog.alterations, + key = { it.id } + ) { alteration -> + AlterationToggleItem( + modifier = Modifier + .animateItem() + .background( + color = MaterialTheme.lwa.colorScheme.elevated.base1dp, + shape = MaterialTheme.lwa.shapes.base.small, + ) + .minimumInteractiveComponentSize() + .padding(horizontal = 8.dp), + alteration = alteration, + onAlteration = { + onAlteration( + dialog.characterSheetId, + alteration.id, + alteration.active, + ) + }, + onTag = onTag, + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogFactory.kt new file mode 100644 index 0000000..585cea8 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogFactory.kt @@ -0,0 +1,61 @@ +package com.pixelized.desktop.lwa.ui.composable.character.alterteration + +import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio +import com.pixelized.desktop.lwa.utils.extention.unAccent +import com.pixelized.shared.lwa.model.alteration.Alteration +import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet +import com.pixelized.shared.lwa.model.tag.Tag +import kotlinx.coroutines.flow.StateFlow + +class CharacterSheetAlterationDialogFactory( + private val tagFactory: GMTagFactory, +) { + + fun filterAlteration( + alterations: Collection, + unAccentFilter: String, + selectedTagId: String?, + ): List { + return alterations.filter { + val matchName = it.metadata.name.unAccent().contains( + other = unAccentFilter, + ignoreCase = true + ) + val matchTag = selectedTagId == null || it.tags.contains( + element = selectedTagId + ) + matchName && matchTag + } + } + + fun convertToDialogUio( + characterSheet: CharacterSheet?, + alterations: List, + tagMap: Map, + filter: LwaTextFieldUio, + tags: StateFlow>, + selectedTagId: String?, + ): CharacterSheetAlterationDialogUio? { + if (characterSheet == null) return null + + return CharacterSheetAlterationDialogUio( + characterSheetId = characterSheet.id, + characterName = characterSheet.name, + filter = filter, + tags = tags, + alterations = alterations.map { alteration -> + AlterationToggleItemUio( + id = alteration.id, + label = alteration.metadata.name, + tags = tagFactory.convertToGMTagItemUio( + tags = alteration.tags.mapNotNull { tagMap[it] }, + selectedTagId = selectedTagId + ), + active = characterSheet.alterations.contains(alteration.id), + ) + }, + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogViewModel.kt new file mode 100644 index 0000000..5238221 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/alterteration/CharacterSheetAlterationDialogViewModel.kt @@ -0,0 +1,121 @@ +package com.pixelized.desktop.lwa.ui.composable.character.alterteration + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository +import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository +import com.pixelized.desktop.lwa.repository.tag.TagRepository +import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagFactory +import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio +import com.pixelized.desktop.lwa.utils.extention.unAccent +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flatMapLatest +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.stateIn +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.runBlocking +import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.game_master__alteration__filter +import org.jetbrains.compose.resources.getString + +class CharacterSheetAlterationDialogViewModel( + private val characterSheetRepository: CharacterSheetRepository, + alterationRepository: AlterationRepository, + tagRepository: TagRepository, + dialogFactory: CharacterSheetAlterationDialogFactory, + tagFactory: GMTagFactory, +) : ViewModel() { + + private val selectedCharacterSheetIdFlow = MutableStateFlow(null) + private val selectedAlterationNameFlow = MutableStateFlow("") + private val selectedTagIdFlow = MutableStateFlow(null) + + private val selectedAlterationsFlow = combine( + alterationRepository.alterationFlow.map { it.values }, + selectedAlterationNameFlow.map { it.unAccent() }, + selectedTagIdFlow, + dialogFactory::filterAlteration + ) + + private val filter = LwaTextFieldUio( + enable = true, + isError = MutableStateFlow(false), + valueFlow = selectedAlterationNameFlow, + label = runBlocking { getString(Res.string.game_master__alteration__filter) }, + placeHolder = null, + onValueChange = { selectedAlterationNameFlow.value = it }, + ) + + private val tags: StateFlow> = combine( + tagRepository.alterationsTagFlow(), + selectedTagIdFlow, + ) { tags, selectedTagId -> + tagFactory.convertToGMTagItemUio( + tags = tags.values, + selectedTagId = selectedTagId, + ) + }.stateIn( + scope = viewModelScope, + started = SharingStarted.Lazily, + initialValue = emptyList(), + ) + + @OptIn(ExperimentalCoroutinesApi::class) + val alterationDialog = selectedCharacterSheetIdFlow + .flatMapLatest { characterSheetId -> + combine( + characterSheetRepository.characterDetailFlow(characterSheetId = characterSheetId), + tagRepository.alterationsTagFlow(), + selectedAlterationsFlow, + selectedTagIdFlow, + ) { characterSheet, tagMap, alterations, selectedTagId -> + dialogFactory.convertToDialogUio( + characterSheet = characterSheet, + tagMap = tagMap, + alterations = alterations, + filter = filter, + tags = tags, + selectedTagId = selectedTagId, + ) + } + } + .stateIn( + scope = viewModelScope, + started = SharingStarted.Lazily, + initialValue = null + ) + + fun show(characterSheetId: String?) { + selectedCharacterSheetIdFlow.update { characterSheetId } + } + + fun hide() { + selectedCharacterSheetIdFlow.update { null } + } + + fun selectedTag(id: String) { + selectedTagIdFlow.update { + when (it) { + id -> null + else -> id + } + } + } + + suspend fun toggleAlteration( + characterSheetId: String, + alterationId: String, + active: Boolean, + ) { + characterSheetRepository.updateAlteration( + characterSheetId = characterSheetId, + alterationId = alterationId, + active = active.not(), + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterSheetCharacteristicDialogViewModel.kt similarity index 91% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterSheetCharacteristicDialogViewModel.kt index b8b89f3..68dc92d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterDetailCharacteristicDialogViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/characteristic/CharacterSheetCharacteristicDialogViewModel.kt @@ -4,19 +4,15 @@ import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository -import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogUio.Characteristic import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory -import com.pixelized.shared.lwa.model.campaign.factory.CampaignJsonFactory import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent -class CharacterDetailCharacteristicDialogViewModel( +class CharacterSheetCharacteristicDialogViewModel( private val characterSheetRepository: CharacterSheetRepository, - private val campaignRepository: CampaignRepository, private val alterationRepository: AlterationRepository, - private val campaignJsonFactory: CampaignJsonFactory, private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory, private val factory: CharacterSheetCharacteristicDialogFactory, private val network: NetworkRepository, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialog.kt similarity index 92% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialog.kt index 7c8ed01..4e1c2f8 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/dialog/DiminishedStatDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialog.kt @@ -1,4 +1,4 @@ -package com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog +package com.pixelized.desktop.lwa.ui.composable.character.diminished import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource @@ -40,7 +40,7 @@ import lwacharactersheet.composeapp.generated.resources.dialog__confirm_action import org.jetbrains.compose.resources.stringResource @Stable -data class CharacterSheetDiminishedStatDialogUio( +data class CharacterSheetDiminishedDialogUio( val characterSheetId: String, val label: String, val value: () -> TextFieldValue, @@ -48,16 +48,16 @@ data class CharacterSheetDiminishedStatDialogUio( ) @Composable -fun DiminishedStatDialog( - dialog: State, - onConfirm: (CharacterSheetDiminishedStatDialogUio) -> Unit, +fun CharacterSheetDiminishedDialog( + dialog: State, + onConfirm: (CharacterSheetDiminishedDialogUio) -> Unit, onDismissRequest: () -> Unit, ) { dialog.value?.let { Dialog( onDismissRequest = onDismissRequest, content = { - DiminishedDialogContent( + CharacterSheetDiminishedContent( dialog = it, onConfirm = onConfirm, onDismissRequest = onDismissRequest, @@ -68,9 +68,9 @@ fun DiminishedStatDialog( } @Composable -private fun DiminishedDialogContent( - dialog: CharacterSheetDiminishedStatDialogUio, - onConfirm: (CharacterSheetDiminishedStatDialogUio) -> Unit, +private fun CharacterSheetDiminishedContent( + dialog: CharacterSheetDiminishedDialogUio, + onConfirm: (CharacterSheetDiminishedDialogUio) -> Unit, onDismissRequest: () -> Unit, ) { val typography = MaterialTheme.typography diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogFactory.kt index e2fb881..9e07bde 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogFactory.kt @@ -5,7 +5,6 @@ import androidx.compose.ui.text.TextRange import androidx.compose.ui.text.input.TextFieldValue import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDiminishedStatDialogUio import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory import com.pixelized.shared.lwa.model.alteration.FieldAlteration import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet @@ -20,7 +19,7 @@ class CharacterSheetDiminishedDialogFactory( ) { suspend fun convertToDialogUio( characterSheetId: String?, - ) : CharacterSheetDiminishedStatDialogUio? { + ) : CharacterSheetDiminishedDialogUio? { if (characterSheetId == null) return null @@ -45,7 +44,7 @@ class CharacterSheetDiminishedDialogFactory( selection = TextRange(index = 0), ) ) - return CharacterSheetDiminishedStatDialogUio( + return CharacterSheetDiminishedDialogUio( characterSheetId = characterSheetId, label = getString(resource = Res.string.character_sheet__diminished__label), value = { textFieldValue.value }, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogViewModel.kt similarity index 78% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedViewModel.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogViewModel.kt index d29b517..a95b7b7 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/diminished/CharacterSheetDiminishedDialogViewModel.kt @@ -4,16 +4,15 @@ import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.lifecycle.ViewModel import com.pixelized.desktop.lwa.repository.network.NetworkRepository -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDiminishedStatDialogUio import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent -class CharacterSheetDiminishedViewModel( +class CharacterSheetDiminishedDialogViewModel( private val networkRepository: NetworkRepository, private val factory: CharacterSheetDiminishedDialogFactory, ) : ViewModel() { - private val _diminishedDialog = mutableStateOf(null) - val diminishedDialog: State get() = _diminishedDialog + private val _diminishedDialog = mutableStateOf(null) + val diminishedDialog: State get() = _diminishedDialog suspend fun showDiminishedDialog( characterSheetId: String?, @@ -28,7 +27,7 @@ class CharacterSheetDiminishedViewModel( } suspend fun changeDiminished( - dialog: CharacterSheetDiminishedStatDialogUio, + dialog: CharacterSheetDiminishedDialogUio, ) { val diminished = dialog.value().text.toIntOrNull() ?: 0 networkRepository.share( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/textfield/LwaTextField.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/textfield/LwaTextField.kt index 22fdf75..cd9cf61 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/textfield/LwaTextField.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/textfield/LwaTextField.kt @@ -22,9 +22,9 @@ import kotlinx.coroutines.flow.MutableStateFlow data class LwaTextFieldUio( val enable: Boolean = true, val isError: MutableStateFlow, - val labelFlow: MutableStateFlow?, val valueFlow: MutableStateFlow, - val placeHolderFlow: MutableStateFlow?, + val label: String?, + val placeHolder: String?, val onValueChange: (String) -> Unit, ) @@ -46,8 +46,6 @@ fun LwaTextField( Modifier } - val label = field.labelFlow?.collectAsState() - val placeHolder = field.placeHolderFlow?.collectAsState() val value = field.valueFlow.collectAsState() val isError = field.isError.collectAsState() @@ -60,7 +58,7 @@ fun LwaTextField( }, enabled = field.enable, singleLine = singleLine, - placeholder = placeHolder?.value?.let { + placeholder = field.placeHolder?.let { { Text( overflow = TextOverflow.Ellipsis, @@ -70,7 +68,7 @@ fun LwaTextField( } }, isError = isError.value, - label = label?.value?.let { + label = field.label?.let { { Text( overflow = TextOverflow.Ellipsis, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollOverlay.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollOverlay.kt index abf2ea1..d679796 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollOverlay.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/overlay/roll/RollOverlay.kt @@ -88,7 +88,7 @@ private fun RollOverlayKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt index db91e06..5d6f2cd 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/CampaignScreen.kt @@ -11,6 +11,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.Stable import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -30,15 +31,18 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.ui.composable.blur.BlurContent import com.pixelized.desktop.lwa.ui.composable.blur.rememberBlurContentController -import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialog +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog +import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialog +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToLevelScreen import com.pixelized.desktop.lwa.ui.overlay.portrait.PortraitOverlay import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel -import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.rememberTransitionAnimation import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.npc.NpcRibbon import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player.PlayerRibbon @@ -46,7 +50,6 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.CampaignChat import com.pixelized.desktop.lwa.ui.screen.campaign.text.CampaignChatViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.CampaignToolbar import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.CampaignToolbarViewModel -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialog import kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel @@ -58,8 +61,9 @@ val LocalCampaignLayoutScope = compositionLocalOf { fun CampaignScreen( playerDetailViewModel: CharacterDetailViewModel = koinViewModel(key = "player"), npcDetailViewModel: CharacterDetailViewModel = koinViewModel(key = "npc"), - characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel = koinViewModel(), - dismissedViewModel: CharacterSheetDiminishedViewModel = koinViewModel(), + characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel = koinViewModel(), + dismissedViewModel: CharacterSheetDiminishedDialogViewModel = koinViewModel(), + alterationViewModel: CharacterSheetAlterationDialogViewModel = koinViewModel(), campaignViewModel: CampaignToolbarViewModel = koinViewModel(), campaignChatViewModel: CampaignChatViewModel = koinViewModel(), ) { @@ -124,6 +128,7 @@ fun CampaignScreen( detailViewModel = npcDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, + alterationViewModel = alterationViewModel, ) }, rightPanel = { @@ -150,6 +155,7 @@ fun CampaignScreen( detailViewModel = playerDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, + alterationViewModel = alterationViewModel, ) }, ) @@ -174,7 +180,7 @@ fun CampaignScreen( }, ) - DiminishedStatDialog( + CharacterSheetDiminishedDialog( dialog = dismissedViewModel.diminishedDialog, onConfirm = { diminished -> scope.launch { @@ -192,10 +198,32 @@ fun CampaignScreen( ) } + CharacterSheetAlterationDialog( + dialog = alterationViewModel.alterationDialog.collectAsState(), + onConfirm = { }, + onTag = { + alterationViewModel.selectedTag(id = it) + }, + onAlteration = { characterSheetId, alterationId, active -> + scope.launch { + alterationViewModel.toggleAlteration(characterSheetId, alterationId, active) + } + }, + onDismissRequest = { + blurController.hide() + alterationViewModel.hide() + }, + ) + CampaignKeyHandler( onDismissRequest = { - playerDetailViewModel.hideCharacter() - npcDetailViewModel.hideCharacter() + val noDialog = characteristicDialogViewModel.statChangeDialog.value == null + && dismissedViewModel.diminishedDialog.value == null + && alterationViewModel.alterationDialog.value == null + if (noDialog) { + playerDetailViewModel.hideCharacter() + npcDetailViewModel.hideCharacter() + } } ) } @@ -293,7 +321,7 @@ private fun CampaignKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetail.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetail.kt index ca2f729..7b33086 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetail.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetail.kt @@ -32,9 +32,10 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.LocalRollHostState import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController -import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogUio -import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedViewModel +import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel import com.pixelized.desktop.lwa.ui.overlay.roll.RollAction import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeader import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderUio @@ -60,8 +61,9 @@ fun CharacterDetailPanel( blurController: BlurContentController, transitionSpec: AnimatedContentTransitionScope.() -> ContentTransform = rememberTransitionAnimation(), detailViewModel: CharacterDetailViewModel, - characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel, - characterDiminishedViewModel: CharacterSheetDiminishedViewModel, + characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel, + characterDiminishedViewModel: CharacterSheetDiminishedDialogViewModel, + alterationViewModel: CharacterSheetAlterationDialogViewModel, ) { val roll = LocalRollHostState.current val scope = rememberCoroutineScope() @@ -74,6 +76,10 @@ fun CharacterDetailPanel( onDismissRequest = { detailViewModel.hideCharacter() }, + onAlteration = { + blurController.show() + alterationViewModel.show(characterSheetId = it) + }, onDiminished = { scope.launch { blurController.show() @@ -141,6 +147,7 @@ fun CharacterDetailAnimatedPanel( detail: State, transitionSpec: AnimatedContentTransitionScope.() -> ContentTransform, onDismissRequest: (characterSheetId: String) -> Unit, + onAlteration: (characterSheetId: String) -> Unit, onDiminished: (characterSheetId: String) -> Unit, onHp: (characterSheetId: String) -> Unit, onPp: (characterSheetId: String) -> Unit, @@ -172,6 +179,7 @@ fun CharacterDetailAnimatedPanel( header = it.header.collectAsState(), sheet = it.sheet.collectAsState(), onDismissRequest = { onDismissRequest(it.characterSheetId) }, + onAlteration = { onAlteration(it.characterSheetId) }, onDiminished = { onDiminished(it.characterSheetId) }, onHp = { onHp(it.characterSheetId) }, onPp = { onPp(it.characterSheetId) }, @@ -194,6 +202,7 @@ fun CharacterDetailContent( shape: Shape = MaterialTheme.lwa.shapes.panel, header: State, sheet: State, + onAlteration: () -> Unit, onDismissRequest: () -> Unit, onDiminished: () -> Unit, onHp: () -> Unit, @@ -217,6 +226,7 @@ fun CharacterDetailContent( .fillMaxWidth(), header = header, onDismissRequest = onDismissRequest, + onAlteration = onAlteration, onDiminished = onDiminished, onHp = onHp, onPp = onPp, @@ -242,7 +252,7 @@ fun CharacterDetailContent( @Stable fun rememberTransitionAnimation( direction: LayoutDirection = LayoutDirection.Rtl, -) : AnimatedContentTransitionScope.() -> ContentTransform { +): AnimatedContentTransitionScope.() -> ContentTransform { return remember { val mul = if (direction == LayoutDirection.Rtl) 1 else -1 { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailFactory.kt index 662cc0f..7419247 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailFactory.kt @@ -1,5 +1,6 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio import com.pixelized.desktop.lwa.ui.overlay.roll.RollAction @@ -55,6 +56,7 @@ class CharacterDetailFactory( suspend fun convertToCharacterDetailHeaderUio( characterSheetId: String, characterSheet: CharacterSheet?, + settings: Settings, alterations: Map>, ): CharacterDetailHeaderUio? { if (characterSheet == null) return null @@ -71,6 +73,7 @@ class CharacterDetailFactory( characterSheetId = characterSheetId, portrait = alteredCharacterSheet.portrait, diminished = alteredCharacterSheet.diminished, + alteration = settings.isAdmin ?: false, name = alteredCharacterSheet.name, level = alteredCharacterSheet.level, hp = "${maxHp - alteredCharacterSheet.damage}", diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailViewModel.kt index 3e1e59b..a22dfbb 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.network.NetworkRepository +import com.pixelized.desktop.lwa.repository.settings.SettingsRepository import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted @@ -17,6 +18,7 @@ import kotlinx.coroutines.launch class CharacterDetailViewModel( private val characterSheetRepository: CharacterSheetRepository, private val alterationRepository: AlterationRepository, + settingRepository: SettingsRepository, private val characterDetailFactory: CharacterDetailFactory, private val network: NetworkRepository, ) : ViewModel() { @@ -32,10 +34,12 @@ class CharacterDetailViewModel( header = combine( characterSheetRepository.characterDetailFlow(characterSheetId = characterSheetId), alterationRepository.fieldAlterationsFlow(characterSheetId = characterSheetId), - ) { characterSheet, alterations -> + settingRepository.settingsFlow() + ) { characterSheet, alterations, settings, -> characterDetailFactory.convertToCharacterDetailHeaderUio( characterSheetId = characterSheetId, characterSheet = characterSheet, + settings = settings, alterations = alterations, ) }.stateIn( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/header/CharacterDetailHeader.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/header/CharacterDetailHeader.kt index dbf8705..363f25d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/header/CharacterDetailHeader.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/header/CharacterDetailHeader.kt @@ -1,6 +1,7 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header 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 @@ -43,13 +44,13 @@ import lwacharactersheet.composeapp.generated.resources.ic_close_24dp import lwacharactersheet.composeapp.generated.resources.ic_cognition_24dp import lwacharactersheet.composeapp.generated.resources.ic_heart_24dp import lwacharactersheet.composeapp.generated.resources.ic_heart_plus_24dp -import lwacharactersheet.composeapp.generated.resources.ic_near_me import lwacharactersheet.composeapp.generated.resources.ic_shield_24dp import lwacharactersheet.composeapp.generated.resources.ic_skull_24dp import lwacharactersheet.composeapp.generated.resources.ic_swords_24dp import lwacharactersheet.composeapp.generated.resources.ic_water_drop_24dp import lwacharactersheet.composeapp.generated.resources.ic_pan_tool_24dp import lwacharactersheet.composeapp.generated.resources.ic_azm_24dp +import lwacharactersheet.composeapp.generated.resources.ic_blur_on_24dp import lwacharactersheet.composeapp.generated.resources.ic_directions_run_24dp import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource @@ -59,6 +60,7 @@ data class CharacterDetailHeaderUio( val characterSheetId: String, val portrait: String?, val diminished: Int, + val alteration: Boolean, val name: String, val level: Int, val hp: String, @@ -91,6 +93,7 @@ fun CharacterDetailHeader( iconSize: Dp = MaterialTheme.lwa.size.sheet.subCategory, header: State, onDismissRequest: () -> Unit, + onAlteration: () -> Unit, onDiminished: () -> Unit, onHp: () -> Unit, onPp: () -> Unit, @@ -124,6 +127,22 @@ fun CharacterDetailHeader( ), ) } + AnimatedVisibility( + visible = header.value?.alteration == true, + enter = fadeIn(), + exit = fadeOut(), + ) { + IconButton( + onClick = onAlteration, + ) { + Icon( + modifier = Modifier.size(size = 24.dp), + painter = painterResource(Res.drawable.ic_blur_on_24dp), + tint = MaterialTheme.colors.primary, + contentDescription = null, + ) + } + } Box { IconButton( onClick = onDiminished, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetPage.kt index 45e45f6..d81249e 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetPage.kt @@ -57,7 +57,7 @@ import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.LocalWindowController import com.pixelized.desktop.lwa.ui.composable.blur.BlurContent import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController -import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedViewModel +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipLayout import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio @@ -69,7 +69,7 @@ import com.pixelized.desktop.lwa.ui.overlay.roll.RollPage import com.pixelized.desktop.lwa.ui.overlay.roll.RollViewModel import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio.Characteristic import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialog -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialog +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialog import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.preview.rememberCharacterSheetPreview import com.pixelized.desktop.lwa.utils.preview.ContentPreview import kotlinx.coroutines.launch @@ -132,7 +132,7 @@ data class CharacterSheetPageUio( @Composable fun CharacterSheetPage( viewModel: CharacterSheetViewModel = koinViewModel(), - diminishedDialogViewModel: CharacterSheetDiminishedViewModel = koinViewModel(), + diminishedDialogViewModel: CharacterSheetDiminishedDialogViewModel = koinViewModel(), rollViewModel: RollViewModel = koinViewModel(), ) { val windowController = LocalWindowController.current @@ -248,7 +248,7 @@ fun CharacterSheetPage( }, ) - DiminishedStatDialog( + CharacterSheetDiminishedDialog( dialog = viewModel.diminishedDialog, onConfirm = { scope.launch { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt index 47495ca..7ae9aa4 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/detail/CharacterSheetViewModel.kt @@ -10,7 +10,7 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetReposit import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.navigation.screen.destination.CharacterSheetDestination import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialogUio -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.CharacterSheetDiminishedStatDialogUio +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogUio import com.pixelized.shared.lwa.protocol.websocket.CharacterSheetEvent import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.combine @@ -35,8 +35,8 @@ class CharacterSheetViewModel( private val _displayRollOverlay = mutableStateOf(false) val displayRollOverlay: State get() = _displayRollOverlay - private val _diminishedDialog = mutableStateOf(null) - val diminishedDialog: State get() = _diminishedDialog + private val _diminishedDialog = mutableStateOf(null) + val diminishedDialog: State get() = _diminishedDialog val sheetFlow = combine( characterRepository.characterDetailFlow(characterSheetId = argument.characterSheetId), diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditFactory.kt index 2f62679..10312e3 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditFactory.kt @@ -497,21 +497,19 @@ class CharacterSheetEditFactory( fun createLwaTextField( enable: Boolean = true, isError: Boolean = false, + value: String? = null, label: String? = null, placeholder: String? = null, - value: String? = null, ): LwaTextFieldUio { val valueFlow = MutableStateFlow(value ?: "") - val labelFlow = MutableStateFlow(label) - val placeholderFlow = MutableStateFlow(placeholder) val isErrorFlow = MutableStateFlow(isError) return LwaTextFieldUio( enable = enable, isError = isErrorFlow, - labelFlow = labelFlow, valueFlow = valueFlow, - placeHolderFlow = placeholderFlow, + label = label, + placeHolder = placeholder, onValueChange = { valueFlow.value = it }, ) } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditViewModel.kt index 028e642..7150070 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/characterSheet/edit/CharacterSheetEditViewModel.kt @@ -57,11 +57,11 @@ class CharacterSheetEditViewModel( copyDialog.value = CharacterSheetCopyDialogUio( label = getString(Res.string.character_sheet_edit__copy__title), value = LwaTextFieldUio( - labelFlow = MutableStateFlow(getString(Res.string.character_sheet_edit__copy__label)), + label = getString(Res.string.character_sheet_edit__copy__label), isError = error, valueFlow = characterSheetId, - placeHolderFlow = MutableStateFlow(null), - onValueChange = { characterSheetId.value = it }, + placeHolder = null, + onValueChange = { characterSheetId.value = it } ), validate = { characterSheetRepository.checkCharacterSheetIdValidity( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditFactory.kt index 1bf238b..daea8fa 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditFactory.kt @@ -40,25 +40,25 @@ class GMAlterationEditFactory( id = LwaTextFieldUio( enable = originId == null, isError = MutableStateFlow(false), - labelFlow = MutableStateFlow(getString(Res.string.game_master__alteration__edit_id)), + label = getString(Res.string.game_master__alteration__edit_id), valueFlow = idFlow, - placeHolderFlow = null, + placeHolder = null, onValueChange = { idFlow.value = it }, ), label = LwaTextFieldUio( enable = true, isError = MutableStateFlow(false), - labelFlow = MutableStateFlow(getString(Res.string.game_master__alteration__edit_label)), + label = getString(Res.string.game_master__alteration__edit_label), valueFlow = labelFlow, - placeHolderFlow = null, + placeHolder = null, onValueChange = { labelFlow.value = it }, ), description = LwaTextFieldUio( enable = true, isError = MutableStateFlow(false), - labelFlow = MutableStateFlow(getString(Res.string.game_master__alteration__edit_description)), + label = getString(Res.string.game_master__alteration__edit_description), valueFlow = descriptionFlow, - placeHolderFlow = null, + placeHolder = null, onValueChange = { descriptionFlow.value = it }, ), tags = tagFlow, @@ -77,17 +77,17 @@ class GMAlterationEditFactory( id = LwaTextFieldUio( enable = true, isError = MutableStateFlow(false), - labelFlow = MutableStateFlow(getString(Res.string.game_master__alteration__edit_field_id)), + label = getString(Res.string.game_master__alteration__edit_field_id), valueFlow = idFlow, - placeHolderFlow = null, + placeHolder = null, onValueChange = { idFlow.value = it }, ), expression = LwaTextFieldUio( enable = true, isError = MutableStateFlow(false), - labelFlow = MutableStateFlow(getString(Res.string.game_master__alteration__edit_field_expression)), + label = getString(Res.string.game_master__alteration__edit_field_expression), valueFlow = expressionFlow, - placeHolderFlow = null, + placeHolder = null, onValueChange = { expressionFlow.value = it }, ) ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditPage.kt index bf0d269..d6a6da9 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/edit/GMAlterationEditPage.kt @@ -365,7 +365,7 @@ private fun AlterationEditKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/list/GMAlterationViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/list/GMAlterationViewModel.kt index d30b99c..2bb1646 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/list/GMAlterationViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/alteration/list/GMAlterationViewModel.kt @@ -32,10 +32,10 @@ class GMAlterationViewModel( val filter = LwaTextFieldUio( enable = true, - labelFlow = MutableStateFlow(runBlocking { getString(Res.string.game_master__character__filter) }), + label = runBlocking { getString(Res.string.game_master__character__filter) }, valueFlow = filterValue, isError = MutableStateFlow(false), - placeHolderFlow = MutableStateFlow(null), + placeHolder = null, onValueChange = { filterValue.value = it }, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterPage.kt index 8d59e70..e92d357 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterPage.kt @@ -34,16 +34,18 @@ import androidx.compose.ui.unit.LayoutDirection import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.LocalBlurController import com.pixelized.desktop.lwa.LocalWindowController -import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialog +import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog -import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedViewModel +import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialog +import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio import com.pixelized.desktop.lwa.ui.navigation.window.destination.navigateToCharacterSheetEdit import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.rememberTransitionAnimation -import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialog import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.GMFilterHeader import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors @@ -60,8 +62,9 @@ import org.koin.compose.viewmodel.koinViewModel fun GMCharacterPage( viewModel: GMCharacterViewModel = koinViewModel(), characterDetailViewModel: CharacterDetailViewModel = koinViewModel(), - characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel = koinViewModel(), - dismissedViewModel: CharacterSheetDiminishedViewModel = koinViewModel(), + characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel = koinViewModel(), + dismissedViewModel: CharacterSheetDiminishedDialogViewModel = koinViewModel(), + alterationViewModel: CharacterSheetAlterationDialogViewModel = koinViewModel(), ) { val windows = LocalWindowController.current val blurController = LocalBlurController.current @@ -111,6 +114,7 @@ fun GMCharacterPage( detailViewModel = characterDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, + alterationViewModel = alterationViewModel, ) CharacterSheetCharacteristicDialog( @@ -132,7 +136,7 @@ fun GMCharacterPage( }, ) - DiminishedStatDialog( + CharacterSheetDiminishedDialog( dialog = dismissedViewModel.diminishedDialog, onConfirm = { diminished -> scope.launch { @@ -148,6 +152,23 @@ fun GMCharacterPage( dismissedViewModel.hideDiminishedDialog() }, ) + + CharacterSheetAlterationDialog( + dialog = alterationViewModel.alterationDialog.collectAsState(), + onConfirm = { }, + onTag = { + alterationViewModel.selectedTag(id = it) + }, + onAlteration = { characterSheetId, alterationId, active -> + scope.launch { + alterationViewModel.toggleAlteration(characterSheetId, alterationId, active) + } + }, + onDismissRequest = { + blurController.hide() + alterationViewModel.hide() + }, + ) } GameMasterCharacterKeyHandler( @@ -253,7 +274,7 @@ private fun GameMasterCharacterKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterViewModel.kt index 162334b..979e115 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/character/list/GMCharacterViewModel.kt @@ -22,7 +22,6 @@ import kotlinx.coroutines.runBlocking import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.game_master__character__filter import org.jetbrains.compose.resources.getString -import java.text.Collator class GMCharacterViewModel( private val networkRepository: NetworkRepository, @@ -38,10 +37,10 @@ class GMCharacterViewModel( val filter = LwaTextFieldUio( enable = true, - labelFlow = MutableStateFlow(runBlocking { getString(Res.string.game_master__character__filter) }), + label = runBlocking { getString(Res.string.game_master__character__filter) }, valueFlow = filterValue, isError = MutableStateFlow(false), - placeHolderFlow = MutableStateFlow(null), + placeHolder = null, onValueChange = { filterValue.value = it }, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/GMFilterHeader.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/GMFilterHeader.kt index 1f00d37..178506b 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/GMFilterHeader.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/GMFilterHeader.kt @@ -24,12 +24,14 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTag import com.pixelized.desktop.lwa.ui.screen.gamemaster.common.tag.GMTagUio +import com.pixelized.desktop.lwa.ui.theme.color.component.LwaTextFieldColors import com.pixelized.desktop.lwa.ui.theme.lwa import kotlinx.coroutines.launch import lwacharactersheet.composeapp.generated.resources.Res @@ -54,6 +56,7 @@ fun GMFilterHeader( LwaTextField( modifier = Modifier.fillMaxWidth(), field = filter, + colors = LwaTextFieldColors(backgroundColor = Color.Transparent), trailingIcon = { val value = filter.valueFlow.collectAsState() AnimatedVisibility( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/tag/GMTagFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/tag/GMTagFactory.kt index 76e7d4c..238b93d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/tag/GMTagFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/common/tag/GMTagFactory.kt @@ -28,9 +28,10 @@ class GMTagFactory { ): List { return tags .map { tag -> - convertToGMTagItemUio( - tag = tag, - selectedTagId = selectedTagId, + GMTagUio( + id = tag.id, + label = tag.label, + highlight = tag.id == selectedTagId, ) } .sortedWith( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt index 213f817..f0fe845 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/levelup/LevelScreen.kt @@ -411,7 +411,7 @@ private fun LevelUpKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt index ce63a65..b3ff792 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt @@ -132,7 +132,7 @@ private fun SettingsKeyHandler( ) { KeyHandler { when { - it.type == KeyEventType.KeyUp && it.key == Key.Escape -> { + it.type == KeyEventType.KeyDown && it.key == Key.Escape -> { onDismissRequest() true } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/component/LwaTextFieldColors.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/component/LwaTextFieldColors.kt index 1267ee9..d3598a1 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/component/LwaTextFieldColors.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/component/LwaTextFieldColors.kt @@ -17,4 +17,16 @@ fun LwaTextFieldColors( backgroundColor = colors.elevated.base1dp, disabledIndicatorColor = Color.Transparent, unfocusedIndicatorColor = Color.Transparent, +) + +@Composable +@Stable +fun LwaTextFieldColors( + backgroundColor: Color = MaterialTheme.lwa.colorScheme.elevated.base1dp, + disabledIndicatorColor: Color = Color.Transparent, + unfocusedIndicatorColor: Color = Color.Transparent, +): TextFieldColors = TextFieldDefaults.textFieldColors( + backgroundColor = backgroundColor, + disabledIndicatorColor = disabledIndicatorColor, + unfocusedIndicatorColor = unfocusedIndicatorColor, ) \ No newline at end of file