From 07ed4ce5793c200d0f36373be09d96797dee9ada Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Thu, 20 Mar 2025 14:32:19 +0100 Subject: [PATCH] Refactor the setting data class + change the roll text message --- .../drawable/ic_format_list_numbered_24dp.xml | 9 +++ .../composeResources/values/strings.xml | 2 + .../desktop/lwa/DataSyncViewModel.kt | 4 +- .../desktop/lwa/network/LwaClientImpl.kt | 2 +- .../repository/settings/SettingsFactory.kt | 36 +++++---- .../lwa/repository/settings/model/Settings.kt | 29 ++++++-- .../settings/model/SettingsJsonV1.kt | 1 + .../campaign/network/NetworkViewModel.kt | 27 ++++--- .../player/ribbon/CharacterRibbonViewModel.kt | 2 +- .../ui/screen/campaign/text/CampaignChat.kt | 21 +++++- .../campaign/text/CampaignChatViewModel.kt | 61 ++++++++++------ .../campaign/text/TextMessageFactory.kt | 10 +-- .../campaign/text/messages/RollTextMessage.kt | 11 ++- .../ui/screen/settings/SettingsViewModel.kt | 73 +++++++++++++++---- .../desktop/lwa/usecase/SettingsUseCase.kt | 21 ++++-- 15 files changed, 216 insertions(+), 93 deletions(-) create mode 100644 composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml new file mode 100644 index 0000000..202a65d --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_format_list_numbered_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml index 82b5f9c..780f8ed 100644 --- a/composeApp/src/commonMain/composeResources/values/strings.xml +++ b/composeApp/src/commonMain/composeResources/values/strings.xml @@ -207,6 +207,8 @@ 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 + Limite le nombre maximale de messages affichés par le chat. Montée de niveau Level Up ! diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt index 3d29f4f..8d90f6f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt @@ -28,8 +28,8 @@ class DataSyncViewModel( if (settings.playerName.isEmpty()) return networkRepository.connect( - host = settings.host, - port = settings.port, + host = settings.network.host, + port = settings.network.port, ) } 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 b1b2c69..5bf3676 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 @@ -19,7 +19,7 @@ class LwaClientImpl( private val client: HttpClient, setting: SettingsRepository, ) : LwaClient { - private val root = setting.settings().root + private val root = setting.settings().network.root override suspend fun characters(): List = client .get("$root/characters") 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 73f4168..9852842 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 @@ -13,14 +13,15 @@ class SettingsFactory( settings: Settings, ): SettingsJson { return SettingsJsonV1( - host = settings.host, - port = settings.port, + host = settings.network.host, + port = settings.network.port, playerName = settings.playerName, - dynamicDice = settings.dynamicDice, - autoHideChat = settings.autoHideChat, - autoHideDelay = settings.autoHideDelay, - autoShowChat = settings.autoShowChat, - autoScrollChat = settings.autoScrollChat, + dynamicDice = settings.portrait.dynamicDice, + autoHideChat = settings.chat.autoHideChat, + autoHideDelay = settings.chat.autoHideDelay, + autoShowChat = settings.chat.autoShowChat, + autoScrollChat = settings.chat.autoScrollChat, + maxLineCount = settings.chat.maxLineCount, isAdmin = settings.isAdmin, isGameMaster = settings.isGameMaster, ) @@ -39,14 +40,21 @@ class SettingsFactory( ): Settings { val default = useCase.defaultSettings() return Settings( - host = json.host ?: default.host, - port = json.port ?: default.port, playerName = json.playerName ?: default.playerName, - dynamicDice = json.dynamicDice ?: default.dynamicDice, - autoHideChat = json.autoHideChat ?: default.autoHideChat, - autoHideDelay = json.autoHideDelay ?: default.autoHideDelay, - autoShowChat = json.autoShowChat ?: default.autoShowChat, - autoScrollChat = json.autoScrollChat ?: default.autoScrollChat, + network = Settings.Network( + host = json.host ?: default.network.host, + port = json.port ?: default.network.port, + ), + portrait = Settings.Portrait( + dynamicDice = json.dynamicDice ?: default.portrait.dynamicDice, + ), + chat = Settings.Chat( + 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, + ), isAdmin = json.isAdmin ?: default.isAdmin, isGameMaster = json.isGameMaster ?: default.isGameMaster, ) 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 61e2d38..4dcec1d 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 @@ -1,16 +1,29 @@ package com.pixelized.desktop.lwa.repository.settings.model data class Settings( - val host: String, - val port: Int, val playerName: String, - val dynamicDice: Boolean, - val autoHideChat: Boolean, - val autoHideDelay: Int, - val autoShowChat: Boolean, - val autoScrollChat: Boolean, + val portrait: Portrait, + val chat: Chat, + val network: Network, val isAdmin: Boolean? = null, val isGameMaster: Boolean? = null, ) { - val root: String get() = "http://${"${host}:${port}".removePrefix("http://")}" + data class Portrait( + val dynamicDice: Boolean, + ) + + data class Chat( + val autoHideChat: Boolean, + val autoHideDelay: Int, + val autoShowChat: Boolean, + val autoScrollChat: Boolean, + val maxLineCount: Int, + ) + + data class Network( + val host: String, + val port: Int, + ) { + val root: String get() = "http://${"${host}:${port}".removePrefix("http://")}" + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt index 91a2a67..386314f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/settings/model/SettingsJsonV1.kt @@ -12,6 +12,7 @@ data class SettingsJsonV1( val autoHideDelay: Int?, val autoShowChat: 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/screen/campaign/network/NetworkViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt index fa64620..0ff50ae 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/network/NetworkViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackUio import kotlinx.coroutines.CancellationException @@ -32,8 +33,8 @@ class NetworkViewModel( ) : ViewModel() { private val settings = settingsRepository.settings() private val nameFlow = MutableStateFlow(settings.playerName) - private val hostFlow = MutableStateFlow(settings.host) - private val portFlow = MutableStateFlow(settings.port) + private val hostFlow = MutableStateFlow(settings.network.host) + private val portFlow = MutableStateFlow(settings.network.port) private val _networkError = MutableSharedFlow() val networkError: SharedFlow get() = _networkError @@ -57,9 +58,9 @@ class NetworkViewModel( player = name, status = status, host = host, - resetHost = settings.host != host, + resetHost = settings.network.host != host, port = port, - resetPort = settings.port != port, + resetPort = settings.network.port != port, ) }.stateIn( scope = viewModelScope, @@ -71,8 +72,8 @@ class NetworkViewModel( settingsRepository.settingsFlow() .onEach { nameFlow.value = it.playerName - hostFlow.value = it.host - portFlow.value = it.port + hostFlow.value = it.network.host + portFlow.value = it.network.port } .launchIn(viewModelScope) } @@ -86,7 +87,7 @@ class NetworkViewModel( } fun onResetPortChange() { - portFlow.value = settings.port + portFlow.value = settings.network.port } fun onHostChange(host: String) { @@ -94,7 +95,7 @@ class NetworkViewModel( } fun onResetHostChange() { - hostFlow.value = settings.host + hostFlow.value = settings.network.host } suspend fun connect() { @@ -103,14 +104,16 @@ class NetworkViewModel( if ( settings.playerName != nameFlow.value || - settings.host != hostFlow.value || - settings.port != portFlow.value + settings.network.host != hostFlow.value || + settings.network.port != portFlow.value ) { settingsRepository.update( settings = settings.copy( playerName = nameFlow.value, - host = hostFlow.value, - port = portFlow.value + network = Settings.Network( + host = hostFlow.value, + port = portFlow.value, + ), ) ) } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt index 3cff5b6..8f84f32 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/CharacterRibbonViewModel.kt @@ -117,7 +117,7 @@ abstract class CharacterRibbonViewModel( settingsRepository.settingsFlow(), rollHistoryRepository.rolls, ) { settings, roll -> - if (settings.dynamicDice && + if (settings.portrait.dynamicDice && characterId.equals(roll.prefix, roll.characterSheetId, roll.instanceId) ) { state.value = CharacterPortraitRollUio( 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 2c4b8eb..5be2552 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 @@ -32,7 +32,6 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.max import androidx.compose.ui.unit.min import androidx.compose.ui.window.WindowState -import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.navigation.window.LocalWindowState import com.pixelized.desktop.lwa.ui.screen.campaign.CampaignLayoutScope import com.pixelized.desktop.lwa.ui.screen.campaign.LocalCampaignLayoutScope @@ -45,9 +44,27 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessag import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio 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 kotlinx.coroutines.launch import org.koin.compose.viewmodel.koinViewModel +@Stable +data class ChatSettingsUio( + val autoShowChat: Boolean, + val autoScrollChat: Boolean, + val autoHideChat: Boolean, +) { + companion object { + fun default() = with(SettingsUseCase().defaultSettings()) { + ChatSettingsUio( + autoShowChat = chat.autoShowChat, + autoScrollChat = chat.autoScrollChat, + autoHideChat = chat.autoHideChat, + ) + } + } +} + @OptIn(ExperimentalComposeUiApi::class) @Composable fun CampaignChat( @@ -119,7 +136,7 @@ fun CampaignChat( private fun ChatScrollDownEffect( lazyState: LazyListState, messages: State>, - settings: State, + settings: State, displayChat: suspend () -> Unit, hideChat: suspend () -> Unit, ) { 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 1a9978b..8283293 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 @@ -6,40 +6,54 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.network.NetworkRepository import com.pixelized.desktop.lwa.repository.settings.SettingsRepository -import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage +import com.pixelized.shared.lwa.protocol.websocket.SocketMessage import kotlinx.coroutines.flow.SharingStarted -import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.runningFold import kotlinx.coroutines.flow.stateIn class CampaignChatViewModel( + private val settingsRepository: SettingsRepository, networkRepository: NetworkRepository, textMessageFactory: TextMessageFactory, - settingsRepository: SettingsRepository, ) : ViewModel() { - val settings = settingsRepository.settingsFlow() - val chatAnimatedVisibility = Animatable(0f) - private var _messages = emptyList() - val messages: StateFlow> = networkRepository.data - .mapNotNull { message -> - val text = textMessageFactory - .convertToTextMessage(message = message) - ?: return@mapNotNull _messages - - _messages = _messages.toMutableList().also { - it.add(index = it.lastIndex + 1, element = text) - } - _messages - } - .stateIn( - scope = viewModelScope, - started = SharingStarted.Eagerly, - initialValue = _messages, + val settings = settingsRepository.settingsFlow().map { + ChatSettingsUio( + autoShowChat = it.chat.autoShowChat, + autoScrollChat = it.chat.autoScrollChat, + autoHideChat = it.chat.autoHideChat, ) + }.stateIn( + scope = viewModelScope, + started = SharingStarted.Eagerly, + initialValue = ChatSettingsUio.default(), + ) + + val messages = combine( + settingsRepository.settingsFlow(), + networkRepository.data.runningFold( + initial = mutableListOf(), + operation = List::plus + ) + ) { settings, messages -> + messages.mapNotNull { message -> + textMessageFactory.convertToTextMessage( + settings = settings, + message = message, + ) + }.takeLast( + n = settings.chat.maxLineCount, + ) + }.stateIn( + scope = viewModelScope, + started = SharingStarted.Eagerly, + initialValue = emptyList(), + ) suspend fun displayChat() { chatAnimatedVisibility.animateTo( @@ -48,11 +62,12 @@ class CampaignChatViewModel( } suspend fun hideChat() { + val settings = settingsRepository.settingsFlow().value chatAnimatedVisibility.animateTo( targetValue = 0f, animationSpec = tween( durationMillis = 2000, - delayMillis = settings.value.autoHideDelay * 1000, + delayMillis = settings.chat.autoHideDelay * 1000, ) ) } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt index 3b6a121..b5e40a6 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/TextMessageFactory.kt @@ -1,12 +1,11 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.text -import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository +import com.pixelized.desktop.lwa.repository.settings.model.Settings import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.CharacteristicTextMessageUio import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.DiminishedTextMessageUio import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.RollTextMessageUio import com.pixelized.desktop.lwa.ui.screen.campaign.text.messages.TextMessage -import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Damage import com.pixelized.shared.lwa.model.campaign.CampaignJsonV1.CharacterInstanceJsonV1.CharacteristicV1.Power import com.pixelized.shared.lwa.protocol.websocket.CampaignMessage @@ -26,13 +25,12 @@ import kotlin.math.abs class TextMessageFactory( private val characterSheetRepository: CharacterSheetRepository, - private val alterationRepository: AlterationRepository, - private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory, ) { private val formatId = SimpleDateFormat("yyyy/MM/dd-HH:mm:ss:SSS") private val formatTime = SimpleDateFormat("HH:mm:ss") suspend fun convertToTextMessage( + settings: Settings, message: SocketMessage, ): TextMessage? { val time = message.timestamp @@ -44,6 +42,8 @@ class TextMessageFactory( .characterPreview(characterId = message.characterSheetId) ?: return null + val isGm = settings.isGameMaster ?: false + RollTextMessageUio( id = "${message.uuid}-${message.timestamp}", timestamp = formatTime.format(time), @@ -51,7 +51,7 @@ class TextMessageFactory( skillLabel = message.skillLabel, rollDifficulty = message.rollDifficulty, rollValue = message.rollValue, - rollSuccessLimit = message.rollSuccessLimit, + rollSuccessLimit = takeIf { isGm }?.let { message.rollSuccessLimit }, resultLabel = message.resultLabel, resultType = when (message.critical) { RollMessage.Critical.CRITICAL_SUCCESS -> RollTextMessageUio.Critical.CRITICAL_SUCCESS diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt index 3d477cd..8287452 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/text/messages/RollTextMessage.kt @@ -8,7 +8,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.pixelized.desktop.lwa.ui.theme.lwa @@ -72,7 +71,6 @@ fun RollTextMessage( Text( modifier = Modifier.alignByBaseline(), style = MaterialTheme.lwa.typography.chat.text, - fontWeight = FontWeight.ExtraLight, overflow = TextOverflow.Ellipsis, maxLines = 1, text = stringResource(Res.string.roll_history__item__throw), @@ -114,7 +112,7 @@ fun RollTextMessage( style = MaterialTheme.lwa.typography.chat.text, overflow = TextOverflow.Ellipsis, maxLines = 1, - text = "${message.rollValue}", + text = "(${message.rollValue}", ) message.rollSuccessLimit?.let { Text( @@ -125,6 +123,13 @@ fun RollTextMessage( text = "/$it", ) } + Text( + modifier = Modifier.alignByBaseline(), + style = MaterialTheme.lwa.typography.chat.text, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + text = ")", + ) } message.rollDifficulty?.let { Text( 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 d3f374f..bc72c57 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 @@ -12,6 +12,7 @@ import com.pixelized.desktop.lwa.usecase.SettingsUseCase import kotlinx.coroutines.launch import lwacharactersheet.composeapp.generated.resources.Res 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 @@ -28,6 +29,8 @@ import lwacharactersheet.composeapp.generated.resources.settings__chat_log__sect import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_description import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_tile import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__section +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_title +import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_description class SettingsViewModel( @@ -48,7 +51,11 @@ class SettingsViewModel( description = Res.string.settings__player_portrait__dyn_dice_description, checked = booleanStates.dynamicDice, onToggle = { - settingsRepository.update(settings = settings.value.copy(dynamicDice = it)) + settingsRepository.update( + settings = settings.value.copy( + portrait = settings.value.portrait.copy(dynamicDice = it) + ) + ) }, ), SettingSectionUio( @@ -60,7 +67,11 @@ class SettingsViewModel( description = Res.string.settings__chat_log__auto_show_description, checked = booleanStates.autoShowChat, onToggle = { - settingsRepository.update(settings = settings.value.copy(autoShowChat = it)) + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoShowChat = it) + ) + ) }, ), SettingToggleItemUio( @@ -69,7 +80,11 @@ class SettingsViewModel( description = Res.string.settings__chat_log__auto_hide_description, checked = booleanStates.autoHideChat, onToggle = { - settingsRepository.update(settings = settings.value.copy(autoHideChat = it)) + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoHideChat = it) + ) + ) }, ), SettingNumberItemUio( @@ -80,7 +95,11 @@ class SettingsViewModel( value = intStates.autoHideDelay, onValueChange = { if (it in 0..999) { - settingsRepository.update(settings = settings.value.copy(autoHideDelay = it)) + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoHideDelay = it) + ) + ) } } ), @@ -90,19 +109,40 @@ class SettingsViewModel( description = Res.string.settings__chat_log__auto_scroll_description, checked = booleanStates.autoScrollChat, onToggle = { - settingsRepository.update(settings = settings.value.copy(autoScrollChat = it)) + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(autoScrollChat = it) + ) + ) }, ), + SettingNumberItemUio( + icon = Res.drawable.ic_format_list_numbered_24dp, + title = Res.string.settings__chat_log__line_count_title, + description = Res.string.settings__chat_log__line_count_description, + enable = mutableStateOf(true), + value = intStates.maxLineCount, + onValueChange = { + if (it in 0..999) { + settingsRepository.update( + settings = settings.value.copy( + chat = settings.value.chat.copy(maxLineCount = it) + ) + ) + } + } + ), ) init { viewModelScope.launch { settingsRepository.settingsFlow().collect { settings -> - booleanStates.dynamicDice.value = settings.dynamicDice - booleanStates.autoShowChat.value = settings.autoShowChat - booleanStates.autoHideChat.value = settings.autoHideChat - intStates.autoHideDelay.value = settings.autoHideDelay - booleanStates.autoScrollChat.value = settings.autoScrollChat + booleanStates.dynamicDice.value = settings.portrait.dynamicDice + 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 } } } @@ -120,17 +160,20 @@ class SettingsViewModel( } private val HashMap>.dynamicDice - get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.dynamicDice) } + get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.portrait.dynamicDice) } private val HashMap>.autoShowChat - get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.autoShowChat) } + get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.chat.autoShowChat) } private val HashMap>.autoHideChat - get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.autoHideChat) } + get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.chat.autoHideChat) } private val HashMap>.autoHideDelay - get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.autoHideDelay) } + get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.chat.autoHideDelay) } private val HashMap>.autoScrollChat - get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.autoScrollChat) } + get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.chat.autoScrollChat) } + + private val HashMap>.maxLineCount + get() = getOrPut("MAX_LINE_COUNT") { mutableStateOf(settings.value.chat.maxLineCount) } } \ No newline at end of file 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 8cc524e..c1f1d63 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 @@ -5,14 +5,21 @@ import com.pixelized.desktop.lwa.repository.settings.model.Settings class SettingsUseCase { fun defaultSettings(): Settings = Settings( - host = DEFAULT_HOST, - port = DEFAULT_PORT, playerName = "", - dynamicDice = true, - autoHideChat = true, - autoHideDelay = 8, - autoShowChat = true, - autoScrollChat = true, + portrait = Settings.Portrait( + dynamicDice = true + ), + chat = Settings.Chat( + autoHideChat = true, + autoHideDelay = 8, + autoShowChat = true, + autoScrollChat = true, + maxLineCount = 200, + ), + network = Settings.Network( + host = DEFAULT_HOST, + port = DEFAULT_PORT, + ), isAdmin = null, isGameMaster = null, )