diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_more_down_24dp.svg b/composeApp/src/commonMain/composeResources/drawable/ic_more_down_24dp.svg deleted file mode 100644 index febe0eb..0000000 --- a/composeApp/src/commonMain/composeResources/drawable/ic_more_down_24dp.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - \ No newline at end of file diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index dcb2884..4f9d158 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -269,6 +269,12 @@ Délai pour les Dés dynamiques Délai après lequel les dés dynamiques disparaissent. Chatlog options + Afficher automatiquement le chat + Affiche automatiquement le chat lors de la réception d'un message + Cacher automatiquement le chat + Cache automatiquement le chat au bout d'un certain temps + Délai pour cacher le chat + Délai après lequel le chat disparaît Défilement automatique Défilement automatique du chat vers le dernier message reçu lors de la réception de ce dernier. Nombre de lignes de textes visibles @@ -323,17 +329,5 @@ Consommable Ajouter une alteration Édition de personnage - Synchronisation du serveur - Demander au serveur d'invalider son cache - Soigner les personnages joueurs - Cette action réinitialisera les points de vie, de pouvoir et d'état diminué de chaque personnage joueur présent dans le groupe. - Cacher le groupe de personnages joueur - Cacher le panneau latéral gauche pour tous les joueurs. - Montrer les personnages joueurs - Montrer le panneau latéral gauche pour tous les joueurs. - Cacher le groupe de npcs - Cacher le panneau latéral droit pour tous les joueurs. - Montrer le groupe de npcs - Montrer le panneau latéral droit pour tous les joueurs. \ No newline at end of file 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 650a4cf..78e7204 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/Module.kt @@ -40,14 +40,13 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.Characte import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderFactory import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.CharacterDetailInventoryFactory -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.NpcRibbonViewModel -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonViewModel +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.npc.NpcRibbonViewModel +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player.PlayerRibbonViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.text.CampaignChatViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.text.TextMessageFactory import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.CampaignToolbarViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.toolbar.links.ResourcesViewModel import com.pixelized.desktop.lwa.ui.screen.gamemaster.GameMasterViewModel -import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionUseCase import com.pixelized.desktop.lwa.ui.screen.gamemaster.action.GMActionViewModel import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditFactory import com.pixelized.desktop.lwa.ui.screen.gamemaster.alteration.edit.GMAlterationEditViewModel @@ -199,5 +198,4 @@ val viewModelDependencies val useCaseDependencies get() = module { factoryOf(::SettingsUseCase) - factoryOf(::GMActionUseCase) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt index f9b4f03..8924ff2 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/SettingsFactory.kt @@ -3,7 +3,6 @@ package com.pixelized.desktop.lwa.repository.settings import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.repository.settings.model.SettingsJson import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV1 -import com.pixelized.desktop.lwa.repository.settings.model.SettingsJsonV2 import com.pixelized.desktop.lwa.usecase.SettingsUseCase @@ -13,13 +12,15 @@ class SettingsFactory( fun convertToJson( settings: Settings, ): SettingsJson { - return SettingsJsonV2( + return SettingsJsonV1( host = settings.network.host, port = settings.network.port, playerName = settings.playerName, dynamicDice = settings.portrait.dynamicDice, dynamicDiceDelay = settings.portrait.dynamicDiceDelay, - showChat = settings.chat.showChat, + autoHideChat = settings.chat.autoHideChat, + autoHideDelay = settings.chat.autoHideDelay, + autoShowChat = settings.chat.autoShowChat, autoScrollChat = settings.chat.autoScrollChat, maxLineCount = settings.chat.maxLineCount, isAdmin = settings.isAdmin, @@ -32,7 +33,6 @@ class SettingsFactory( ): Settings { return when (json) { is SettingsJsonV1 -> convertFromJsonV1(json) - is SettingsJsonV2 -> convertFromJsonV2(json) } } @@ -51,31 +51,9 @@ class SettingsFactory( dynamicDiceDelay = json.dynamicDiceDelay ?: default.portrait.dynamicDiceDelay, ), chat = Settings.Chat( - showChat = default.chat.showChat, - autoScrollChat = json.autoScrollChat ?: default.chat.autoScrollChat, - maxLineCount = json.maxLineCount ?: default.chat.maxLineCount, - ), - isAdmin = json.isAdmin ?: default.isAdmin, - isGameMaster = json.isGameMaster ?: default.isGameMaster, - ) - } - - private fun convertFromJsonV2( - json: SettingsJsonV2, - ): Settings { - val default = useCase.defaultSettings() - return Settings( - playerName = json.playerName ?: default.playerName, - network = Settings.Network( - host = json.host ?: default.network.host, - port = json.port ?: default.network.port, - ), - portrait = Settings.Portrait( - dynamicDice = json.dynamicDice ?: default.portrait.dynamicDice, - dynamicDiceDelay = json.dynamicDiceDelay ?: default.portrait.dynamicDiceDelay, - ), - chat = Settings.Chat( - showChat = json.showChat ?: default.chat.showChat, + autoHideChat = json.autoHideChat ?: default.chat.autoHideChat, + autoHideDelay = json.autoHideDelay ?: default.chat.autoHideDelay, + autoShowChat = json.autoShowChat ?: default.chat.autoShowChat, autoScrollChat = json.autoScrollChat ?: default.chat.autoScrollChat, maxLineCount = json.maxLineCount ?: default.chat.maxLineCount, ), diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt index 2ef636a..80fc9ee 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/Settings.kt @@ -14,7 +14,9 @@ data class Settings( ) data class Chat( - val showChat: Boolean, + val autoHideChat: Boolean, + val autoHideDelay: Int, + val autoShowChat: Boolean, val autoScrollChat: Boolean, val maxLineCount: Int, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV2.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV2.kt deleted file mode 100644 index 7e54773..0000000 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV2.kt +++ /dev/null @@ -1,17 +0,0 @@ -package com.pixelized.desktop.lwa.repository.settings.model - -import kotlinx.serialization.Serializable - -@Serializable -data class SettingsJsonV2( - val host: String?, - val port: Int?, - val playerName: String?, - val dynamicDice: Boolean?, - val dynamicDiceDelay: Int?, - val showChat: Boolean?, - val autoScrollChat: Boolean?, - val maxLineCount: Int?, - val isGameMaster: Boolean?, - val isAdmin: Boolean?, -) : SettingsJson \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/LwaDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/LwaDialog.kt index 80e8b46..856450d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/LwaDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/character/LwaDialog.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.State import androidx.compose.runtime.remember @@ -19,8 +18,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog -import com.pixelized.desktop.lwa.LocalBlurController -import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox import com.pixelized.desktop.lwa.utils.extention.onPreviewEscape @@ -32,7 +29,6 @@ object LwaDialogDefault { @Composable fun LwaDialog( modifier: Modifier = Modifier, - blur: BlurContentController? = LocalBlurController.current, paddings: PaddingValues = LwaDialogDefault.paddings, color: Color = MaterialTheme.colors.surface, state: State, @@ -41,16 +37,6 @@ fun LwaDialog( content: @Composable BoxScope.(T) -> Unit, ) { state.value?.let { dialog -> - - blur?.let { - DisposableEffect("LwaDialog") { - blur.show() - onDispose { - blur.hide() - } - } - } - Dialog( onDismissRequest = onDismissRequest, content = { 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 index 8dea0f1..23ead9d 100644 --- 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 @@ -19,7 +19,6 @@ import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.minimumInteractiveComponentSize import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState @@ -29,12 +28,13 @@ 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.LocalBlurController -import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController +import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackHandler +import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackUio 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.SharedFlow import kotlinx.coroutines.flow.StateFlow import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.ic_close_24dp @@ -52,23 +52,12 @@ data class CharacterSheetAlterationDialogUio( @OptIn(ExperimentalComposeUiApi::class) @Composable fun CharacterSheetAlterationDialog( - blur: BlurContentController? = LocalBlurController.current, dialog: State, onTag: (String) -> Unit, onAlteration: (characterSheetId: String, alterationId: String, active: Boolean) -> Unit, onDismissRequest: () -> Unit, ) { dialog.value?.let { - - blur?.let { - DisposableEffect("LwaDialog") { - blur.show() - onDispose { - blur.hide() - } - } - } - Dialog( properties = DialogProperties( usePlatformDefaultWidth = false, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/confirmation/ConfirmationDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/confirmation/ConfirmationDialog.kt deleted file mode 100644 index 7aab76c..0000000 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/confirmation/ConfirmationDialog.kt +++ /dev/null @@ -1,98 +0,0 @@ -package com.pixelized.desktop.lwa.ui.composable.confirmation - -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.padding -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.material.TextButton -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Stable -import androidx.compose.runtime.State -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.unit.dp -import com.pixelized.desktop.lwa.LocalBlurController -import com.pixelized.desktop.lwa.ui.composable.character.LwaDialog -import lwacharactersheet.composeapp.generated.resources.Res -import lwacharactersheet.composeapp.generated.resources.dialog__cancel_action -import lwacharactersheet.composeapp.generated.resources.dialog__confirm_action -import org.jetbrains.compose.resources.stringResource - -@Stable -data class ConfirmationDialogUio( - val title: String, - val description: String, - val onConfirmRequest: () -> Unit, - val onDismissRequest: () -> Unit, -) - -@Stable -object ConfirmationDialogDefault { - - @Stable - val paddings = PaddingValues(start = 16.dp, top = 16.dp, end = 16.dp) - - @Stable - val spacings: Dp = 8.dp -} - -@OptIn(ExperimentalComposeUiApi::class) -@Composable -fun ConfirmationDialog( - modifier: Modifier = Modifier, - paddingValues: PaddingValues = ConfirmationDialogDefault.paddings, - spacing: Dp = ConfirmationDialogDefault.spacings, - dialog: State, -) { - LwaDialog( - modifier = modifier, - blur = LocalBlurController.current, - state = dialog, - onDismissRequest = { dialog.value?.onDismissRequest?.invoke() }, - onConfirm = { dialog.value?.onConfirmRequest?.invoke() }, - ) { - Column( - modifier = Modifier.padding(paddingValues = paddingValues), - verticalArrangement = Arrangement.spacedBy(space = spacing), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - style = MaterialTheme.typography.caption, - text = it.title, - ) - Text( - style = MaterialTheme.typography.body1, - text = it.description, - ) - Row( - modifier = Modifier.align(alignment = Alignment.End), - horizontalArrangement = Arrangement.spacedBy( - space = spacing / 2, - alignment = Alignment.End, - ), - ) { - TextButton( - onClick = it.onDismissRequest, - ) { - Text( - color = MaterialTheme.colors.primaryVariant, - text = stringResource(Res.string.dialog__cancel_action) - ) - } - TextButton( - onClick = it.onConfirmRequest, - ) { - Text( - color = MaterialTheme.colors.primary, - text = stringResource(Res.string.dialog__confirm_action) - ) - } - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/tooltip/BasicTooltipLayout.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/tooltip/BasicTooltipLayout.kt index f5e6fee..f5da12e 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/tooltip/BasicTooltipLayout.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/composable/tooltip/BasicTooltipLayout.kt @@ -5,7 +5,7 @@ import androidx.compose.foundation.TooltipPlacement import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.widthIn +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.MaterialTheme import androidx.compose.material.Surface @@ -56,7 +56,7 @@ fun BasicTooltipLayout( tips = tooltip, tooltip = { BasicTooltip( - modifier = Modifier.widthIn(max = 448.dp), + modifier = Modifier.width(width = 448.dp), elevation = elevation, tooltip = it, ) @@ -72,9 +72,7 @@ private fun BasicTooltip( tooltip: BasicTooltipUio, ) { Surface( - modifier = Modifier - .padding(16.dp) - .then(other = modifier), + modifier = Modifier.padding(16.dp).then(other = modifier), color = MaterialTheme.colors.surface, elevation = elevation, shape = remember { RoundedCornerShape(4.dp) } 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 bd773ae..e43f9c7 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 @@ -1,5 +1,6 @@ package com.pixelized.desktop.lwa.ui.screen.campaign +import androidx.compose.foundation.background import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxHeight @@ -19,6 +20,7 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.key.Key import androidx.compose.ui.input.key.KeyEvent import androidx.compose.ui.input.key.KeyEventType @@ -51,9 +53,9 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetai import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.DetailPanelUio import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.rememberTransitionAnimation -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbon -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.NpcRibbonViewModel -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbonViewModel +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.npc.NpcRibbon +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player.PlayerRibbon +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player.PlayerRibbonViewModel 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 @@ -70,7 +72,6 @@ val LocalCampaignLayoutScope = compositionLocalOf { fun CampaignScreen( playerRibbonViewModel: PlayerRibbonViewModel = koinViewModel(), playerDetailViewModel: CharacterDetailPanelViewModel = koinViewModel(key = "player"), - npcRibbonViewModel: NpcRibbonViewModel = koinViewModel(), npcDetailViewModel: CharacterDetailPanelViewModel = koinViewModel(key = "npc"), characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel = koinViewModel(), dismissedViewModel: CharacterSheetDiminishedDialogViewModel = koinViewModel(), @@ -121,10 +122,10 @@ fun CampaignScreen( } }, leftPanel = { - CharacterRibbon( - modifier = Modifier.fillMaxHeight(), + PlayerRibbon( + modifier = Modifier.fillMaxHeight() + .background(color = Color.Black.copy(alpha = 0.5f)), viewModel = playerRibbonViewModel, - layoutDirection = LayoutDirection.Ltr, onCharacterLeftClick = { scope.launch { playerDetailViewModel.showCharacter( @@ -147,10 +148,9 @@ fun CampaignScreen( ) }, rightPanel = { - CharacterRibbon( - modifier = Modifier.fillMaxHeight(), - viewModel = npcRibbonViewModel, - layoutDirection = LayoutDirection.Rtl, + NpcRibbon( + modifier = Modifier.fillMaxHeight() + .background(color = Color.Black.copy(alpha = 0.5f)), onCharacterLeftClick = { scope.launch { npcDetailViewModel.showCharacter( @@ -176,10 +176,11 @@ fun CampaignScreen( CharacterDetailPanel( modifier = Modifier .padding(all = 8.dp) - .padding(start = MaterialTheme.lwa.size.portrait.minimized.width + 8.dp) + .padding(start = MaterialTheme.lwa.size.portrait.minimized.width * 2 + 20.dp) .width(width = 128.dp * 4) .fillMaxHeight(), transitionSpec = rememberTransitionAnimation(direction = LayoutDirection.Ltr), + blurController = blurController, detailPanelViewModel = playerDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, @@ -193,10 +194,11 @@ fun CampaignScreen( CharacterDetailPanel( modifier = Modifier .padding(all = 8.dp) - .padding(end = MaterialTheme.lwa.size.portrait.minimized.width + 8.dp) + .padding(end = MaterialTheme.lwa.size.portrait.minimized.width * 2 + 20.dp) .width(width = 128.dp * 4) .fillMaxHeight(), transitionSpec = rememberTransitionAnimation(direction = LayoutDirection.Rtl), + blurController = blurController, detailPanelViewModel = npcDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, @@ -216,7 +218,7 @@ fun CampaignScreen( characteristicDialogViewModel.changeSubCharacteristic( characterSheetId = dialog.characterSheetId, characteristic = dialog.characteristic, - useArmor = dialog.enableArmor?.checked?.value == true, + useArmor= dialog.enableArmor?.checked?.value == true, value = dialog.value.valueFlow.value.toIntOrNull() ?: 0, ) characteristicDialogViewModel.hideSubCharacteristicDialog() diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailPanel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailPanel.kt index 6119193..ccf2552 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailPanel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/CharacterDetailPanel.kt @@ -15,6 +15,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding import androidx.compose.foundation.pager.HorizontalPager import androidx.compose.foundation.pager.PagerState import androidx.compose.foundation.pager.rememberPagerState @@ -30,6 +31,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Shape 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.alterteration.CharacterSheetAlterationDialogViewModel @@ -72,6 +74,7 @@ enum class DetailPanelUio { @Composable fun CharacterDetailPanel( modifier: Modifier = Modifier, + blurController: BlurContentController, transitionSpec: AnimatedContentTransitionScope.() -> ContentTransform = rememberTransitionAnimation(), detailPanelViewModel: CharacterDetailPanelViewModel, characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel, @@ -118,10 +121,12 @@ fun CharacterDetailPanel( } }, onAlteration = { + blurController.show() alterationViewModel.show(characterSheetId = it) }, onDiminished = { scope.launch { + blurController.show() characterDiminishedViewModel.showDiminishedDialog( characterSheetId = it ) @@ -129,6 +134,7 @@ fun CharacterDetailPanel( }, onHp = { scope.launch { + blurController.show() characteristicDialogViewModel.showSubCharacteristicDialog( characterSheetId = it, characteristic = CharacterSheetCharacteristicDialogUio.Characteristic.Damage, @@ -137,6 +143,7 @@ fun CharacterDetailPanel( }, onPp = { scope.launch { + blurController.show() characteristicDialogViewModel.showSubCharacteristicDialog( characterSheetId = it, characteristic = CharacterSheetCharacteristicDialogUio.Characteristic.Fatigue, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt index 0221bef..714593f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/detail/inventory/CharacterDetailInventory.kt @@ -107,6 +107,7 @@ fun CharacterDetailInventory( itemDetailDialogViewModel: ItemDetailDialogViewModel = koinViewModel(), inventory: State, ) { + val blur = LocalBlurController.current val focus = LocalFocusManager.current val scope = rememberCoroutineScope() @@ -119,12 +120,14 @@ fun CharacterDetailInventory( spacing = spacing, inventory = unWrap, onPurse = { + blur.show() purseViewModel.showPurseDialog( characterSheetId = it, ) focus.clearFocus(force = true) }, onItem = { item -> + blur.show() itemDetailDialogViewModel.showItemDialog( characterSheetId = item.characterSheetId, inventoryId = item.inventoryId, @@ -133,6 +136,7 @@ fun CharacterDetailInventory( focus.clearFocus(force = true) }, onAddItem = { + blur.show() inventoryDialogViewModel.showInventoryDialog( characterSheetId = it, ) @@ -162,6 +166,7 @@ fun CharacterDetailInventory( PurseDialog( dialog = purseViewModel.purseDialog.collectAsState(), onDismissRequest = { + blur.hide() purseViewModel.hidePurseDialog() }, onSwapSign = { @@ -170,6 +175,7 @@ fun CharacterDetailInventory( onConfirm = { scope.launch { if (purseViewModel.confirmPurse(dialog = it)) { + blur.hide() purseViewModel.hidePurseDialog() } } @@ -179,9 +185,11 @@ fun CharacterDetailInventory( InventoryDialog( dialog = inventoryDialogViewModel.inventoryDialog.collectAsState(), onDismissRequest = { + blur.hide() inventoryDialogViewModel.hideInventoryDialog() }, onItem = { dialog, itemId -> + blur.show() itemDetailDialogViewModel.showItemDialog( characterSheetId = dialog.characterSheetId, inventoryId = null, @@ -193,6 +201,7 @@ fun CharacterDetailInventory( ItemDetailDialog( dialog = itemDetailDialogViewModel.itemDialog.collectAsState(), onDismissRequest = { + blur.hide() itemDetailDialogViewModel.hideItemDialog() }, onAddItem = { dialog -> @@ -201,6 +210,7 @@ fun CharacterDetailInventory( dialog = dialog, ) if (result) { + blur.hide() itemDetailDialogViewModel.hideItemDialog() } } @@ -211,6 +221,7 @@ fun CharacterDetailInventory( dialog = dialog, ) if (result) { + blur.hide() itemDetailDialogViewModel.hideItemDialog() } } @@ -222,6 +233,7 @@ fun CharacterDetailInventory( inventoryId = dialog.inventoryId, ) if (result) { + blur.hide() itemDetailDialogViewModel.hideItemDialog() } } @@ -233,6 +245,7 @@ fun CharacterDetailInventory( inventoryId = dialog.inventoryId, ) if (result) { + blur.hide() itemDetailDialogViewModel.hideItemDialog() } } @@ -244,6 +257,7 @@ fun CharacterDetailInventory( inventoryId = dialog.inventoryId, ) if (result) { + blur.hide() itemDetailDialogViewModel.hideItemDialog() } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbon.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbon.kt deleted file mode 100644 index c67da46..0000000 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbon.kt +++ /dev/null @@ -1,70 +0,0 @@ -package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.graphicsLayer -import androidx.compose.ui.platform.LocalLayoutDirection -import androidx.compose.ui.unit.LayoutDirection -import androidx.compose.ui.unit.dp -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonPortrait -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonRoll -import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonAlteration - -@Composable -fun CharacterRibbon( - modifier: Modifier = Modifier, - layoutDirection: LayoutDirection, - viewModel: CharacterRibbonViewModel, - padding: PaddingValues = PaddingValues(all = 8.dp), - onCharacterLeftClick: (characterSheetId: String) -> Unit, - onCharacterRightClick: (characterSheetId: String) -> Unit, - onLevelUp: (characterSheetId: String) -> Unit, -) { - val characters = viewModel.characters.collectAsState() - - CompositionLocalProvider( - LocalLayoutDirection provides layoutDirection - ) { - LazyColumn( - modifier = modifier, - contentPadding = padding, - verticalArrangement = Arrangement.spacedBy(space = 8.dp) - ) { - items( - items = characters.value, - key = { it.characterSheetId }, - ) { - Row( - modifier = Modifier - .animateItem() - .graphicsLayer { if (it.hideOverruled) this.alpha = 0.3f }, - horizontalArrangement = Arrangement.spacedBy(space = 4.dp), - ) { - Box { - CharacterRibbonPortrait( - character = it.portrait, - onCharacterLeftClick = { onCharacterLeftClick(it.characterSheetId) }, - onCharacterRightClick = { onCharacterRightClick(it.characterSheetId) }, - onLevelUp = { onLevelUp(it.characterSheetId) }, - ) - CharacterRibbonRoll( - value = viewModel.roll(characterSheetId = it.characterSheetId).value, - ) - } - CharacterRibbonAlteration( - status = it.status, - direction = LayoutDirection.Ltr, - ) - } - } - } - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt index bdb8729..838967d 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonAlteration.kt @@ -32,7 +32,6 @@ import com.pixelized.desktop.lwa.ui.theme.lwa @Stable data class CharacterRibbonAlterationUio( - val icon: String, val tooltips: BasicTooltipUio?, ) @@ -45,56 +44,60 @@ fun CharacterRibbonAlteration( direction: LayoutDirection, status: List>, ) { - val currentDirection = LocalLayoutDirection.current + val currentDirection: LayoutDirection = LocalLayoutDirection.current - Row( - modifier = Modifier - .animateContentSize() - .size(size = size) - .then(other = modifier), - horizontalArrangement = Arrangement.spacedBy(space = 4.dp), + CompositionLocalProvider( + LocalLayoutDirection provides direction ) { - status.forEach { columns -> - Column( - modifier = Modifier.animateContentSize(), - verticalArrangement = Arrangement.spacedBy(space = 2.dp), + Row( + modifier = Modifier + .animateContentSize() + .size(size = size) + .then(other = modifier), + horizontalArrangement = Arrangement.spacedBy(space = 4.dp), + ) { + CompositionLocalProvider( + LocalLayoutDirection provides currentDirection ) { - CompositionLocalProvider( - LocalLayoutDirection provides LayoutDirection.Ltr - ) { - columns.forEach { - BasicTooltipLayout( - delayMillis = 0, - tooltip = it.tooltips, - tooltipPlacement = remember(currentDirection) { - TooltipPlacement.ComponentRect( - anchor = when (direction) { - LayoutDirection.Ltr -> Alignment.CenterEnd - LayoutDirection.Rtl -> Alignment.CenterStart - }, - alignment = when (direction) { - LayoutDirection.Ltr -> Alignment.CenterEnd - LayoutDirection.Rtl -> Alignment.CenterStart - }, - ) - }, - content = { - AnimatedContent( - targetState = it.icon, - transitionSpec = { fadeIn() togetherWith fadeOut() }, - ) { icon -> - AsyncImage( - modifier = Modifier.size(24.dp), - model = ImageRequest.Builder(context = PlatformContext.INSTANCE) - .data(data = icon) - .size(size = 48) - .build(), - filterQuality = FilterQuality.High, - contentDescription = null, + status.forEach { columns -> + Column( + modifier = Modifier.animateContentSize(), + verticalArrangement = Arrangement.spacedBy(space = 2.dp), + ) { + columns.forEach { + BasicTooltipLayout( + delayMillis = 0, + tooltip = it.tooltips, + tooltipPlacement = remember(currentDirection) { + TooltipPlacement.ComponentRect( + anchor = when (direction) { + LayoutDirection.Ltr -> Alignment.TopStart + LayoutDirection.Rtl -> Alignment.TopEnd + }, + alignment = when (direction) { + LayoutDirection.Ltr -> Alignment.BottomEnd + LayoutDirection.Rtl -> Alignment.BottomStart + }, ) + }, + content = { + AnimatedContent( + targetState = it.icon, + transitionSpec = { fadeIn() togetherWith fadeOut() }, + ) { icon -> + AsyncImage( + modifier = Modifier.size(24.dp), + model = ImageRequest.Builder(context = PlatformContext.INSTANCE) + .data(data = icon) + .size(size = 48) + .build(), + filterQuality = FilterQuality.High, + contentDescription = null, + ) + } } - } - ) + ) + } } } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbon.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbon.kt new file mode 100644 index 0000000..a9fbfcb --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbon.kt @@ -0,0 +1,64 @@ +package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.npc + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonPortrait +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonRoll +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonAlteration +import org.koin.compose.viewmodel.koinViewModel + +@Composable +fun NpcRibbon( + modifier: Modifier = Modifier, + viewModel: NpcRibbonViewModel = koinViewModel(), + padding: PaddingValues = PaddingValues(all = 8.dp), + onCharacterLeftClick: (characterSheetId: String) -> Unit, + onCharacterRightClick: (characterSheetId: String) -> Unit, + onLevelUp: (characterSheetId: String) -> Unit, +) { + val characters = viewModel.characters.collectAsState() + + LazyColumn( + modifier = modifier, + contentPadding = padding, + verticalArrangement = Arrangement.spacedBy(space = 8.dp) + ) { + items( + items = characters.value, + key = { it.characterSheetId }, + ) { + Row( + modifier = Modifier + .animateItem() + .graphicsLayer { if (it.hideOverruled) this.alpha = 0.3f }, + horizontalArrangement = Arrangement.spacedBy(space = 4.dp), + ) { + CharacterRibbonAlteration( + status = it.status, + direction = LayoutDirection.Rtl, + ) + Box { + CharacterRibbonPortrait( + character = it.portrait, + onCharacterLeftClick = { onCharacterLeftClick(it.characterSheetId) }, + onCharacterRightClick = { onCharacterRightClick(it.characterSheetId) }, + onLevelUp = { onLevelUp(it.characterSheetId) }, + ) + CharacterRibbonRoll( + value = viewModel.roll(characterSheetId = it.characterSheetId).value, + ) + } + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/NpcRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt similarity index 91% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/NpcRibbonViewModel.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt index e029293..3dd6c5b 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/NpcRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt @@ -1,4 +1,4 @@ -package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon +package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.npc import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository @@ -6,6 +6,8 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetReposit import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository import com.pixelized.desktop.lwa.repository.settings.model.Settings +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonFactory +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonViewModel import com.pixelized.shared.lwa.model.campaign.Campaign class NpcRibbonViewModel( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbon.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbon.kt new file mode 100644 index 0000000..37554ad --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbon.kt @@ -0,0 +1,64 @@ +package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.unit.LayoutDirection +import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonPortrait +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonRoll +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.common.CharacterRibbonAlteration +import org.koin.compose.viewmodel.koinViewModel + +@Composable +fun PlayerRibbon( + modifier: Modifier = Modifier, + viewModel: PlayerRibbonViewModel = koinViewModel(), + padding: PaddingValues = PaddingValues(all = 8.dp), + onCharacterLeftClick: (characterSheetId: String) -> Unit, + onCharacterRightClick: (characterSheetId: String) -> Unit, + onLevelUp: (characterSheetId: String) -> Unit, +) { + val characters = viewModel.characters.collectAsState() + + LazyColumn( + modifier = modifier, + contentPadding = padding, + verticalArrangement = Arrangement.spacedBy(space = 8.dp) + ) { + items( + items = characters.value, + key = { it.characterSheetId }, + ) { + Row( + modifier = Modifier + .animateItem() + .graphicsLayer { if (it.hideOverruled) this.alpha = 0.3f }, + horizontalArrangement = Arrangement.spacedBy(space = 4.dp), + ) { + Box { + CharacterRibbonPortrait( + character = it.portrait, + onCharacterLeftClick = { onCharacterLeftClick(it.characterSheetId) }, + onCharacterRightClick = { onCharacterRightClick(it.characterSheetId) }, + onLevelUp = { onLevelUp(it.characterSheetId) }, + ) + CharacterRibbonRoll( + value = viewModel.roll(characterSheetId = it.characterSheetId).value, + ) + } + CharacterRibbonAlteration( + status = it.status, + direction = LayoutDirection.Ltr, + ) + } + } + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/PlayerRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt similarity index 90% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/PlayerRibbonViewModel.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt index df81d36..e80b095 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/PlayerRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt @@ -1,4 +1,4 @@ -package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon +package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.player import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository @@ -6,6 +6,8 @@ import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetReposit import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository import com.pixelized.desktop.lwa.repository.settings.model.Settings +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonFactory +import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.CharacterRibbonViewModel import com.pixelized.shared.lwa.model.campaign.Campaign class PlayerRibbonViewModel( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt index 9af413a..c3a1453 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChat.kt @@ -1,28 +1,18 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.text -import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.animateDpAsState -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.expandIn -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut -import androidx.compose.animation.shrinkOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.heightIn +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.size -import androidx.compose.foundation.layout.width import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Icon -import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect @@ -31,10 +21,13 @@ import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.graphicsLayer +import androidx.compose.ui.input.pointer.PointerEventType +import androidx.compose.ui.input.pointer.onPointerEvent import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max @@ -54,21 +47,21 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessag import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.usecase.SettingsUseCase -import lwacharactersheet.composeapp.generated.resources.Res -import lwacharactersheet.composeapp.generated.resources.ic_more_down_24dp -import org.jetbrains.compose.resources.painterResource +import kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel @Stable data class ChatSettingsUio( - val show: Boolean, - val autoScroll: Boolean, + val autoShowChat: Boolean, + val autoScrollChat: Boolean, + val autoHideChat: Boolean, ) { companion object { fun default() = with(SettingsUseCase().defaultSettings()) { ChatSettingsUio( - show = chat.showChat, - autoScroll = chat.autoScrollChat, + autoShowChat = chat.autoShowChat, + autoScrollChat = chat.autoScrollChat, + autoHideChat = chat.autoHideChat, ) } } @@ -80,9 +73,9 @@ fun CampaignChat( modifier: Modifier = Modifier, chatViewModel: CampaignChatViewModel = koinViewModel(), ) { - + val scope = rememberCoroutineScope() val lazyState = rememberLazyListState() - val campaignLayoutScope = LocalCampaignLayoutScope.current + val animatedChatWidth = rememberAnimatedChatWidth() val colorScheme = MaterialTheme.lwa.colorScheme val messages = chatViewModel.messages.collectAsState() val settings = chatViewModel.settings.collectAsState() @@ -91,61 +84,52 @@ fun CampaignChat( lazyState = lazyState, messages = messages, settings = settings, + displayChat = chatViewModel::displayChat, + hideChat = chatViewModel::hideChat, ) - Row( - modifier = modifier.background( - shape = remember { RoundedCornerShape(8.dp) }, - color = remember { colorScheme.elevated.base1dp.copy(alpha = 0.5f) }, - ), - ) { - AnimatedVisibility( - visible = settings.value.show, - enter = fadeIn() + expandIn(), - exit = fadeOut() + shrinkOut(), - ) { - LazyColumn( - modifier = Modifier - .width(width = campaignLayoutScope.chatOverlay.value.width - (32.dp + 8.dp)) - .heightIn(min = MaterialTheme.lwa.size.portrait.minimized.height * 2 + 8.dp), - state = lazyState, - verticalArrangement = Arrangement.spacedBy( - space = 4.dp, - alignment = Alignment.Bottom, - ), - contentPadding = remember { PaddingValues(all = 8.dp) }, - ) { - items( - items = messages.value, - key = { it.id }, - contentType = { it.javaClass.simpleName } - ) { - when (it) { - is RollTextMessageUio -> RollTextMessage(message = it) - is PurseTextMessageUio -> PurseTextMessage(message = it) - is DiminishedTextMessageUio -> DiminishedTextMessage(message = it) - is CharacteristicTextMessageUio -> CharacteristicTextMessage(message = it) - } - } + Box( + modifier = modifier + .size( + width = animatedChatWidth.value, + height = MaterialTheme.lwa.size.portrait.minimized.height * 2 + 8.dp, + ) + .graphicsLayer { + alpha = chatViewModel.chatAnimatedVisibility.value } - } - Column { - IconButton( - modifier = Modifier.size(size = 32.dp), - onClick = chatViewModel::toggleChat + .background( + shape = remember { RoundedCornerShape(8.dp) }, + color = remember { colorScheme.elevated.base1dp.copy(alpha = 0.5f) }, + ) + .onPointerEvent(eventType = PointerEventType.Enter) { + scope.launch { chatViewModel.displayChat() } + } + .onPointerEvent(eventType = PointerEventType.Exit) { + if (settings.value.autoHideChat) { + scope.launch { chatViewModel.hideChat() } + } + }, + ) { + LazyColumn( + modifier = Modifier.fillMaxSize(), + state = lazyState, + verticalArrangement = Arrangement.spacedBy( + space = 4.dp, + alignment = Alignment.Bottom, + ), + contentPadding = remember { PaddingValues(all = 8.dp) }, + ) { + items( + items = messages.value, + key = { it.id }, + contentType = { it.javaClass.simpleName } ) { - val rotation = animateFloatAsState( - targetValue = if (settings.value.show) 0f else 180f, - ) - Icon( - modifier = Modifier - .size(size = 16.dp) - .graphicsLayer { - this.rotationZ = rotation.value - }, - painter = painterResource(Res.drawable.ic_more_down_24dp), - contentDescription = null, - ) + when (it) { + is RollTextMessageUio -> RollTextMessage(message = it) + is PurseTextMessageUio -> PurseTextMessage(message = it) + is DiminishedTextMessageUio -> DiminishedTextMessage(message = it) + is CharacteristicTextMessageUio -> CharacteristicTextMessage(message = it) + } } } } @@ -156,16 +140,24 @@ private fun ChatScrollDownEffect( lazyState: LazyListState, messages: State>, settings: State, + displayChat: suspend () -> Unit, + hideChat: suspend () -> Unit, ) { LaunchedEffect( key1 = messages.value.lastOrNull()?.id, ) { if (messages.value.isNotEmpty()) { - if (settings.value.autoScroll) { + if (settings.value.autoShowChat) { + displayChat() + } + if (settings.value.autoScrollChat) { lazyState.animateScrollToItem( index = messages.value.lastIndex + 1, ) } + if (settings.value.autoHideChat) { + hideChat() + } } } } @@ -175,26 +167,19 @@ private fun ChatScrollDownEffect( private fun rememberAnimatedChatWidth( campaignScreenScope: CampaignLayoutScope = LocalCampaignLayoutScope.current, windowsState: WindowState = LocalWindowState.current, - settings: State, ): State { val chatWidth = remember(windowsState, campaignScreenScope) { derivedStateOf { - if (settings.value.show) { - val minChatWidth = 64.dp * 8 - val maxChatWidth = 64.dp * 12 - val windowWidth = windowsState.size.width - if (windowWidth != Dp.Unspecified) { - val width = windowWidth - campaignScreenScope.leftPanel.value.width - 16.dp - min(max(width, minChatWidth), maxChatWidth) - } else { - minChatWidth - } + val minChatWidth = 64.dp * 8 + val maxChatWidth = 64.dp * 12 + val windowWidth = windowsState.size.width + if (windowWidth != Dp.Unspecified) { + val width = windowWidth - campaignScreenScope.leftPanel.value.width - 16.dp + min(max(width, minChatWidth), maxChatWidth) } else { - 0.dp + minChatWidth } } } - return animateDpAsState( - targetValue = chatWidth.value, - ) + return animateDpAsState(targetValue = chatWidth.value) } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt index a2fab42..21baec1 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/CampaignChatViewModel.kt @@ -1,5 +1,7 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.text +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.tween import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository @@ -11,20 +13,22 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.runningFold import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch class CampaignChatViewModel( private val settingsRepository: SettingsRepository, - campaignRepository: CampaignRepository, + private val campaignRepository: CampaignRepository, networkRepository: NetworkRepository, textMessageFactory: TextMessageFactory, ) : ViewModel() { + val chatAnimatedVisibility = Animatable(0f) + val settings = settingsRepository.settingsFlow().map { ChatSettingsUio( - show = it.chat.showChat, - autoScroll = it.chat.autoScrollChat, + autoShowChat = it.chat.autoShowChat, + autoScrollChat = it.chat.autoScrollChat, + autoHideChat = it.chat.autoHideChat, ) }.stateIn( scope = viewModelScope, @@ -55,14 +59,20 @@ class CampaignChatViewModel( initialValue = emptyList(), ) - fun toggleChat() { - viewModelScope.launch { - val settings = settingsRepository.settingsFlow().value - settingsRepository.update( - settings = settings.copy( - chat = settings.chat.copy(showChat = settings.chat.showChat.not()) - ) + suspend fun displayChat() { + chatAnimatedVisibility.animateTo( + targetValue = 1f, + ) + } + + suspend fun hideChat() { + val settings = settingsRepository.settingsFlow().value + chatAnimatedVisibility.animateTo( + targetValue = 0f, + animationSpec = tween( + durationMillis = 2000, + delayMillis = settings.chat.autoHideDelay * 1000, ) - } + ) } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionPage.kt index 74860c8..e7a5dcb 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionPage.kt @@ -10,13 +10,12 @@ import androidx.compose.foundation.verticalScroll import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.State +import androidx.compose.runtime.collectAsState import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackHandler -import com.pixelized.desktop.lwa.ui.composable.confirmation.ConfirmationDialog import kotlinx.coroutines.launch import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.ic_camping_24dp @@ -37,8 +36,7 @@ fun GMActionPage( ) { val scope = rememberCoroutineScope() val scroll = rememberScrollState() - val actions = viewModel.actions.collectAsStateWithLifecycle() - val validationDialog = viewModel.validationDialog.collectAsStateWithLifecycle() + val actions = viewModel.actions.collectAsState() GMActionContent( actions = actions, @@ -68,10 +66,6 @@ fun GMActionPage( ErrorSnackHandler( error = viewModel.error, ) - - ConfirmationDialog( - dialog = validationDialog, - ) } @Composable diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionUseCase.kt deleted file mode 100644 index 895f9a0..0000000 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionUseCase.kt +++ /dev/null @@ -1,58 +0,0 @@ -package com.pixelized.desktop.lwa.ui.screen.gamemaster.action - -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.shared.lwa.protocol.websocket.GameAdminEvent -import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent - -class GMActionUseCase( - private val characterRepository: CharacterSheetRepository, - private val networkRepository: NetworkRepository, - private val campaignRepository: CampaignRepository, -) { - suspend fun invalidateServerCache() { - networkRepository.share( - GameAdminEvent.ServerSynchronization( - timestamp = System.currentTimeMillis(), - ) - ) - } - - suspend fun healPlayerParty() { - campaignRepository.campaignFlow().value.characters.forEach { characterSheetId -> - val sheet = characterRepository.characterDetail( - characterSheetId = characterSheetId, - ) ?: return@forEach - - val updated = sheet.copy( - damage = 0, - fatigue = 0, - diminished = 0, - ) - - if (sheet != updated) { - characterRepository.updateCharacter( - sheet = updated, - create = false, - ) - } - } - } - - suspend fun toggleNpcVisibility() { - networkRepository.share( - GameMasterEvent.ToggleNpc( - timestamp = System.currentTimeMillis(), - ) - ) - } - - suspend fun togglePlayerVisibility() { - networkRepository.share( - GameMasterEvent.TogglePlayer( - timestamp = System.currentTimeMillis(), - ) - ) - } -} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionViewModel.kt index c80f8be..3a980c3 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/action/GMActionViewModel.kt @@ -3,36 +3,23 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster.action import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository -import com.pixelized.desktop.lwa.ui.composable.confirmation.ConfirmationDialogUio +import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository +import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackUio +import com.pixelized.shared.lwa.protocol.websocket.GameAdminEvent +import com.pixelized.shared.lwa.protocol.websocket.GameMasterEvent import kotlinx.coroutines.flow.MutableSharedFlow -import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.stateIn -import kotlinx.coroutines.launch -import lwacharactersheet.composeapp.generated.resources.Res -import lwacharactersheet.composeapp.generated.resources.game_master__actions__hide_npc__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__hide_npc__title -import lwacharactersheet.composeapp.generated.resources.game_master__actions__hide_player__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__hide_player__title -import lwacharactersheet.composeapp.generated.resources.game_master__actions__on_server_sync__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__on_server_sync__title -import lwacharactersheet.composeapp.generated.resources.game_master__actions__party_heal__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__party_heal__title -import lwacharactersheet.composeapp.generated.resources.game_master__actions__show_npc__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__show_npc__title -import lwacharactersheet.composeapp.generated.resources.game_master__actions__show_player__description -import lwacharactersheet.composeapp.generated.resources.game_master__actions__show_player__title -import org.jetbrains.compose.resources.StringResource -import org.jetbrains.compose.resources.getString class GMActionViewModel( - private val actionUseCase: GMActionUseCase, - campaignRepository: CampaignRepository, + private val characterRepository: CharacterSheetRepository, + private val networkRepository: NetworkRepository, + private val campaignRepository: CampaignRepository, ) : ViewModel() { private val _error = MutableSharedFlow() @@ -52,102 +39,68 @@ class GMActionViewModel( initialValue = null, ) - private val _validationDialog = MutableStateFlow(null) - val validationDialog: StateFlow = _validationDialog - suspend fun onServerSync() { - showConfirmationDialog( - title = Res.string.game_master__actions__on_server_sync__title, - description = Res.string.game_master__actions__on_server_sync__description, - onConfirmationRequest = { - try { - actionUseCase.invalidateServerCache() - } catch (exception: Exception) { - val message = ErrorSnackUio.from(exception = exception) - _error.emit(message) - } - }, - onDismissRequest = { - _validationDialog.value = null - } - ) + try { + networkRepository.share( + GameAdminEvent.ServerSynchronization( + timestamp = System.currentTimeMillis(), + ) + ) + } catch (exception: Exception) { + val message = ErrorSnackUio.from(exception = exception) + _error.emit(message) + } } suspend fun onPartyHeal() { - showConfirmationDialog( - title = Res.string.game_master__actions__party_heal__title, - description = Res.string.game_master__actions__party_heal__description, - onConfirmationRequest = { - try { - actionUseCase.healPlayerParty() - } catch (exception: Exception) { - val message = ErrorSnackUio.from(exception = exception) - _error.emit(message) - } - }, - ) - } + campaignRepository.campaignFlow().value.characters.forEach { characterSheetId -> + val sheet = characterRepository.characterDetail( + characterSheetId = characterSheetId, + ) ?: return@forEach - suspend fun onPlayerVisibility() { - showConfirmationDialog( - title = when (actions.value?.party) { - true -> Res.string.game_master__actions__hide_player__title - else -> Res.string.game_master__actions__show_player__title - }, - description = when (actions.value?.party) { - true -> Res.string.game_master__actions__hide_player__description - else -> Res.string.game_master__actions__show_player__description - }, - onConfirmationRequest = { + val updated = sheet.copy( + damage = 0, + fatigue = 0, + diminished = 0, + ) + + if (sheet != updated) { try { - actionUseCase.togglePlayerVisibility() + characterRepository.updateCharacter( + sheet = updated, + create = false, + ) } catch (exception: Exception) { val message = ErrorSnackUio.from(exception = exception) _error.emit(message) } - }, - ) + } + } } suspend fun onNpcVisibility() { - showConfirmationDialog( - title = when (actions.value?.npc) { - true -> Res.string.game_master__actions__hide_npc__title - else -> Res.string.game_master__actions__show_npc__title - }, - description = when (actions.value?.npc) { - true -> Res.string.game_master__actions__hide_npc__description - else -> Res.string.game_master__actions__show_npc__description - }, - onConfirmationRequest = { - try { - actionUseCase.toggleNpcVisibility() - } catch (exception: Exception) { - val message = ErrorSnackUio.from(exception = exception) - _error.emit(message) - } - }, - ) + try { + networkRepository.share( + GameMasterEvent.ToggleNpc( + timestamp = System.currentTimeMillis(), + ) + ) + } catch (exception: Exception) { + val message = ErrorSnackUio.from(exception = exception) + _error.emit(message) + } } - private suspend inline fun showConfirmationDialog( - title: StringResource, - description: StringResource, - crossinline onConfirmationRequest: suspend () -> Unit, - crossinline onDismissRequest: () -> Unit = { _validationDialog.value = null }, - ) { - _validationDialog.value = ConfirmationDialogUio( - title = getString(title), - description = getString(description), - onConfirmRequest = { - viewModelScope.launch { - onConfirmationRequest() - onDismissRequest() - } - }, - onDismissRequest = { - onDismissRequest() - }, - ) + suspend fun onPlayerVisibility() { + try { + networkRepository.share( + GameMasterEvent.TogglePlayer( + timestamp = System.currentTimeMillis(), + ) + ) + } catch (exception: Exception) { + val message = ErrorSnackUio.from(exception = exception) + _error.emit(message) + } } } \ No newline at end of file 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 b5e8c3a..79899c8 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 @@ -109,6 +109,7 @@ fun GMCharacterPage( .width(width = 128.dp * 4) .fillMaxHeight(), transitionSpec = rememberTransitionAnimation(direction = LayoutDirection.Rtl), + blurController = blurController, detailPanelViewModel = characterDetailViewModel, characterDiminishedViewModel = dismissedViewModel, characteristicDialogViewModel = characteristicDialogViewModel, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt index 42fd420..6560bb1 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt @@ -15,8 +15,16 @@ import lwacharactersheet.composeapp.generated.resources.ic_fan_focus_24dp import lwacharactersheet.composeapp.generated.resources.ic_format_list_numbered_24dp import lwacharactersheet.composeapp.generated.resources.ic_ifl_24dp import lwacharactersheet.composeapp.generated.resources.ic_timer_24dp +import lwacharactersheet.composeapp.generated.resources.ic_visibility_24dp +import lwacharactersheet.composeapp.generated.resources.ic_visibility_off_24dp +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_delay_description +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_delay_title +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_description +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_title import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_scroll_description import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_scroll_title +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_show_description +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_show_title import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_description import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_title import lwacharactersheet.composeapp.generated.resources.settings__chat_log__section @@ -84,6 +92,48 @@ class SettingsViewModel( SettingSectionUio( title = Res.string.settings__chat_log__section, ), + SettingToggleItemUio( + icon = Res.drawable.ic_visibility_24dp, + title = Res.string.settings__chat_log__auto_show_title, + description = Res.string.settings__chat_log__auto_show_description, + checked = booleanStates.autoShowChat, + onToggle = { + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoShowChat = it) + ) + ) + }, + ), + SettingToggleItemUio( + icon = Res.drawable.ic_visibility_off_24dp, + title = Res.string.settings__chat_log__auto_hide_title, + description = Res.string.settings__chat_log__auto_hide_description, + checked = booleanStates.autoHideChat, + onToggle = { + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoHideChat = it) + ) + ) + }, + ), + SettingNumberItemUio( + icon = Res.drawable.ic_timer_24dp, + title = Res.string.settings__chat_log__auto_hide_delay_title, + description = Res.string.settings__chat_log__auto_hide_delay_description, + enable = booleanStates.autoHideChat, + value = intStates.autoHideDelay, + onValueChange = { + if (it in 0..999) { + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoHideDelay = it) + ) + ) + } + } + ), SettingToggleItemUio( icon = Res.drawable.ic_fan_focus_24dp, title = Res.string.settings__chat_log__auto_scroll_title, @@ -120,6 +170,9 @@ class SettingsViewModel( settingsRepository.settingsFlow().collect { settings -> booleanStates.dynamicDice.value = settings.portrait.dynamicDice intStates.dynamicDiceDelay.value = settings.portrait.dynamicDiceDelay + booleanStates.autoShowChat.value = settings.chat.autoShowChat + booleanStates.autoHideChat.value = settings.chat.autoHideChat + intStates.autoHideDelay.value = settings.chat.autoHideDelay booleanStates.autoScrollChat.value = settings.chat.autoScrollChat intStates.maxLineCount.value = settings.chat.maxLineCount } @@ -144,6 +197,15 @@ class SettingsViewModel( private val HashMap>.dynamicDiceDelay get() = getOrPut("DYNAMIC_DICE_DELAY") { mutableStateOf(settings.value.portrait.dynamicDiceDelay) } + private val HashMap>.autoShowChat + get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.chat.autoShowChat) } + + private val HashMap>.autoHideChat + get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.chat.autoHideChat) } + + private val HashMap>.autoHideDelay + get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.chat.autoHideDelay) } + private val HashMap>.autoScrollChat get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.chat.autoScrollChat) } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/LwaColors.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/LwaColors.kt index 968d573..98bfedc 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/LwaColors.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/color/LwaColors.kt @@ -55,10 +55,7 @@ data class LwaColors( @Composable @Stable fun darkLwaColorTheme( - base: Colors = darkColors( - primary = Color(0xFFBB86FC), - primaryVariant = Color(0xB2BB86FC), - ), + base: Colors = darkColors(), elevated: LwaColors.Elevated = LwaColors.Elevated( base1dp = base.calculateElevatedColor( color = base.surface, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt index d4e325b..357b6ab 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt @@ -8,10 +8,12 @@ class SettingsUseCase { playerName = "", portrait = Settings.Portrait( dynamicDice = true, - dynamicDiceDelay = 8000, + dynamicDiceDelay = 5000, ), chat = Settings.Chat( - showChat = true, + autoHideChat = true, + autoHideDelay = 8, + autoShowChat = true, autoScrollChat = true, maxLineCount = 200, ),