diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_face_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_face_24dp.xml new file mode 100644 index 0000000..881617e --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_face_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_face_retouching_off_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_face_retouching_off_24dp.xml new file mode 100644 index 0000000..3d5a366 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_face_retouching_off_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_group_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_group_24dp.xml new file mode 100644 index 0000000..1adc8c8 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_group_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_group_off_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_group_off_24dp.xml new file mode 100644 index 0000000..2065a5f --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_group_off_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/composeApp/src/commonMain/composeResources/drawable/ic_imagesmode_24dp.xml b/composeApp/src/commonMain/composeResources/drawable/ic_imagesmode_24dp.xml new file mode 100644 index 0000000..d340866 --- /dev/null +++ b/composeApp/src/commonMain/composeResources/drawable/ic_imagesmode_24dp.xml @@ -0,0 +1,9 @@ + + + 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 5ef9b8f..07021bb 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/DataSyncViewModel.kt @@ -39,6 +39,11 @@ class DataSyncViewModel( .onEach { campaignRepository.update() } .launchIn(this) + networkRepository.status + .filter { status -> status == NetworkRepository.Status.CONNECTED } + .onEach { characterRepository.updateCharacterPreviews() } + .launchIn(this) + networkRepository.status .filter { status -> status == NetworkRepository.Status.CONNECTED } .combine(campaignRepository.campaignFlow) { _, campaign: Campaign -> campaign } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt index c08f6bf..c01b14c 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetRepository.kt @@ -16,8 +16,13 @@ class CharacterSheetRepository( private val scope = CoroutineScope(Dispatchers.IO + Job()) val characterSheetPreviewFlow get() = store.previewFlow + val characterDetailFlow get() = store.detailFlow + suspend fun updateCharacterPreviews() { + store.updateCharacterPreviews() + } + fun characterPreview(characterId: String?): CharacterSheetPreview? { return characterSheetPreviewFlow.value.firstOrNull { it.characterSheetId == characterId } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt index c103119..60bae88 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/repository/characterSheet/CharacterSheetStore.kt @@ -32,7 +32,7 @@ class CharacterSheetStore( val scope = CoroutineScope(Dispatchers.IO + Job()) // initial data loading. scope.launch { - _previewFlow.value = charactersPreview() + updateCharacterPreviews() } // data update through WebSocket. scope.launch { @@ -42,6 +42,10 @@ class CharacterSheetStore( // region Rest + suspend fun updateCharacterPreviews() { + _previewFlow.value = charactersPreview() + } + suspend fun charactersPreview(): List { val request = client.characters() val data = request.map { 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 6876e36..e8620dd 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 @@ -21,6 +21,7 @@ class SettingsFactory( autoHideDelay = settings.autoHideDelay, autoShowChat = settings.autoShowChat, autoScrollChat = settings.autoScrollChat, + isAdmin = settings.isAdmin, isGM = settings.isGM, ) } @@ -46,6 +47,7 @@ class SettingsFactory( autoHideDelay = json.autoHideDelay ?: default.autoHideDelay, autoShowChat = json.autoShowChat ?: default.autoShowChat, autoScrollChat = json.autoScrollChat ?: default.autoScrollChat, + isAdmin = json.isAdmin ?: default.isAdmin, isGM = json.isGM ?: default.isGM, ) } 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 eebeeb4..4720233 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 @@ -9,6 +9,7 @@ data class Settings( val autoHideDelay: Int, val autoShowChat: Boolean, val autoScrollChat: Boolean, + val isAdmin: Boolean, val isGM: Boolean, ) { val root: String get() = "http://${"${host}:${port}".removePrefix("http://")}" 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 2c9a7fd..bafe902 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 @@ -13,4 +13,5 @@ data class SettingsJsonV1( val autoShowChat: Boolean?, val autoScrollChat: Boolean?, val isGM: Boolean?, + val isAdmin: Boolean?, ) : SettingsJson \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetEditWindow.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetEditWindow.kt index d6e3336..7bdb165 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetEditWindow.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetEditWindow.kt @@ -17,7 +17,7 @@ class CharacterSheetEditWindow( fun WindowController.navigateToCharacterSheetEdit( characterId: String?, - title: String, + title: String = "", ) { showWindow( window = CharacterSheetEditWindow( @@ -25,7 +25,7 @@ fun WindowController.navigateToCharacterSheetEdit( title = title, size = DpSize( width = 600.dp, - height = maxWindowHeight, + height = maxWindowHeight - 32.dp, ), ) ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetWindow.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetWindow.kt index 3151ed3..5afe104 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetWindow.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/CharacterSheetWindow.kt @@ -18,7 +18,7 @@ class CharacterSheetWindow( fun WindowController.navigateToCharacterSheet( characterId: Campaign.CharacterInstance.Id, - title: String, + title: String = "Feuille de personnage", ) { showWindow( window = CharacterSheetWindow( @@ -26,7 +26,7 @@ fun WindowController.navigateToCharacterSheet( title = title, size = DpSize( width = 400.dp + 64.dp, - height = maxWindowHeight, + height = maxWindowHeight - 32.dp, ), ) ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/RollHistoryWindow.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/RollHistoryWindow.kt index 712dcde..9a352be 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/RollHistoryWindow.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/navigation/window/destination/RollHistoryWindow.kt @@ -22,7 +22,7 @@ fun WindowController.navigateToRollHistory( title = title, size = DpSize( width = 400.dp + 64.dp, - height = maxWindowHeight, + height = maxWindowHeight - 32.dp, ) ) ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt index 8110f7d..ad507ce 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterPortrait.kt @@ -39,6 +39,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.FilterQuality import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import coil3.compose.AsyncImage @@ -60,6 +61,7 @@ object CharacterPortraitDefault { @Stable data class CharacterPortraitUio( val id: Campaign.CharacterInstance.Id, + val idLabel: String?, val portrait: String?, val name: String, val levelUp: Boolean, @@ -79,6 +81,7 @@ data class CharacterPortraitUio( fun CharacterPortrait( modifier: Modifier = Modifier, size: DpSize = CharacterPortraitDefault.size, + levelUpOffset: Dp = 9.dp, character: CharacterPortraitUio, onCharacter: (id: Campaign.CharacterInstance.Id) -> Unit, onLevelUp: (id: Campaign.CharacterInstance.Id) -> Unit, @@ -106,8 +109,18 @@ fun CharacterPortrait( ) } + character.idLabel?.let { label -> + Text( + modifier = Modifier.padding(start = 4.dp, top = 3.dp), + style = MaterialTheme.lwa.typography.portrait.idLabel, + text = label, + ) + } + AnimatedVisibility( - modifier = Modifier.offset(x = (-8).dp, y = (-8).dp), + modifier = Modifier + .align(alignment = Alignment.TopEnd) + .offset(x = levelUpOffset, y = -levelUpOffset), visible = character.levelUp, enter = fadeIn(), exit = fadeOut(), @@ -149,14 +162,12 @@ fun CharacterPortrait( ) Text( modifier = Modifier.alignByBaseline(), - style = MaterialTheme.typography.caption, - fontWeight = FontWeight.Bold, + style = MaterialTheme.lwa.typography.portrait.value, text = "${stats.hp}", ) Text( modifier = Modifier.alignByBaseline(), - style = MaterialTheme.typography.caption, - fontWeight = FontWeight.Light, + style = MaterialTheme.lwa.typography.portrait.max, text = "/${stats.maxHp}", ) } @@ -171,14 +182,12 @@ fun CharacterPortrait( ) Text( modifier = Modifier.alignByBaseline(), - style = MaterialTheme.typography.caption, - fontWeight = FontWeight.Bold, + style = MaterialTheme.lwa.typography.portrait.value, text = "${stats.pp}", ) Text( modifier = Modifier.alignByBaseline(), - fontWeight = FontWeight.Light, - style = MaterialTheme.typography.caption, + style = MaterialTheme.lwa.typography.portrait.max, text = "/${stats.maxPp}", ) } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt index bff235b..8a86e74 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/CharacterRibbonFactory.kt @@ -15,8 +15,9 @@ class CharacterRibbonFactory( alterations: Map>, characterInstanceId: Campaign.CharacterInstance.Id, characterInstance: Campaign.CharacterInstance, - enableDetail: Boolean, - displayCharacterStats: Boolean, + enableCharacterId: Boolean, + enableCharacterSheet: Boolean, + enableCharacterStats: Boolean, ): CharacterPortraitUio? { if (characterSheet == null) return null @@ -27,11 +28,12 @@ class CharacterRibbonFactory( return CharacterPortraitUio( id = characterInstanceId, + idLabel = takeIf { enableCharacterId }?.let { characterInstanceId.instanceId.toString() }, portrait = alteredCharacterSheet.thumbnail, name = alteredCharacterSheet.name, levelUp = alteredCharacterSheet.shouldLevelUp, - enableDetail = enableDetail, - stats = takeIf { displayCharacterStats }?.let { + enableDetail = enableCharacterSheet, + stats = takeIf { enableCharacterStats }?.let { CharacterPortraitUio.StatsDetail( hp = alteredCharacterSheet.maxHp - characterInstance.damage, maxHp = alteredCharacterSheet.maxHp, 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 742a089..45defef 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 @@ -41,6 +41,9 @@ abstract class CharacterRibbonViewModel( abstract val Campaign.data: Map + abstract val enableCharacterSheet: Boolean + abstract val enableCharacterStats: Boolean + /** * This flow is a tad complex so there is an explanation of wtf it's about : * On a campaign update it go through every element of the abstract [data] map and either: @@ -58,14 +61,16 @@ abstract class CharacterRibbonViewModel( combine( characterRepository.characterDetailFlow(characterSheetId = entry.key.characterSheetId), alterationRepository.alterationsFlow(characterInstanceId = entry.key), - ) { sheet, alterations -> + settingsRepository.settingsFlow(), + ) { sheet, alterations, settings -> ribbonFactory.convertToPlayerPortraitUio( characterSheet = sheet, alterations = alterations, characterInstanceId = entry.key, characterInstance = entry.value, - enableDetail = settingsRepository.settings().isGM, - displayCharacterStats = settingsRepository.settings().isGM, + enableCharacterId = settings.isGM, + enableCharacterSheet = enableCharacterSheet || settings.isGM, + enableCharacterStats = enableCharacterStats || settings.isGM, ) } }, 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 index 8612b31..dadc3a6 100644 --- 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 @@ -34,7 +34,9 @@ fun NpcRibbon( items = characters.value, key = { it.id }, ) { - Row { + Row( + modifier = Modifier.animateItem(), + ) { CharacterPortraitRoll( size = CharacterPortraitDefault.size, value = viewModel.roll(characterId = it.id).value, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt index f3637c6..f503b7a 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/npc/NpcRibbonViewModel.kt @@ -25,4 +25,7 @@ class NpcRibbonViewModel( ribbonFactory = ribbonFactory, ) { override val Campaign.data get() = npcs + + override val enableCharacterSheet = false + override val enableCharacterStats = false } \ No newline at end of file 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 index be80778..d8b3c20 100644 --- 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 @@ -33,7 +33,9 @@ fun PlayerRibbon( items = characters.value, key = { it.id }, ) { - Row { + Row( + modifier = Modifier.animateItem(), + ) { CharacterPortrait( character = it, onCharacter = onCharacter, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt index 2c54998..39eb3b1 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/player/PlayerRibbonViewModel.kt @@ -25,4 +25,7 @@ class PlayerRibbonViewModel( ribbonFactory = ribbonFactory, ) { override val Campaign.data get() = characters + + override val enableCharacterSheet = true + override val enableCharacterStats = true } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbar.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbar.kt index d6bd5d1..aa66eda 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbar.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbar.kt @@ -5,7 +5,6 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.DropdownMenu import androidx.compose.material.DropdownMenuItem import androidx.compose.material.Icon @@ -22,7 +21,6 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.clip import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp @@ -57,15 +55,15 @@ fun CampaignToolbar( val title = viewModel.title.collectAsState() val status = viewModel.status.collectAsState() - val isGM = viewModel.isGM.collectAsState() + val isAdmin = viewModel.isAdmin.collectAsState() CampaignToolbarContent( title = title, status = status, - isGM = isGM, + isAdmin = isAdmin, isNetworkMenuOpen = isNetworkMenuOpen, isOverflowMenuOpen = isOverflowMenuOpen, - onGM = { + onAdmin = { windows.navigateToGameMasterWindow() }, onNetwork = { @@ -96,10 +94,10 @@ private fun CampaignToolbarContent( modifier: Modifier = Modifier, title: State, status: State, - isGM: State, + isAdmin: State, isNetworkMenuOpen: State, isOverflowMenuOpen: State, - onGM: () -> Unit, + onAdmin: () -> Unit, onNetwork: () -> Unit, onOverflow: () -> Unit, onRollHistory: () -> Unit, @@ -116,17 +114,16 @@ private fun CampaignToolbarContent( }, actions = { AnimatedVisibility( - visible = isGM.value, + visible = isAdmin.value, enter = fadeIn(), exit = fadeOut(), ) { TextButton( - modifier = Modifier.size(size = 48.dp).clip(shape = CircleShape), - onClick = onGM, + onClick = onAdmin, ) { Text( fontWeight = FontWeight.SemiBold, - text = "GM", + text = "Admin", ) } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbarViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbarViewModel.kt index 0bf23c9..4038da5 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbarViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/toolbar/CampaignToolbarViewModel.kt @@ -25,8 +25,8 @@ class CampaignToolbarViewModel( initialValue = "", ) - val isGM = settingsRepository.settingsFlow() - .map { it.isGM } + val isAdmin = settingsRepository.settingsFlow() + .map { it.isAdmin } .stateIn( scope = viewModelScope, started = SharingStarted.Lazily, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt index 703efc8..f4de737 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterActionUseCase.kt @@ -1,7 +1,7 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio.Action +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio.Action class GameMasterActionUseCase( private val campaignRepository: CampaignRepository, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterFactory.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterFactory.kt index 505328a..bc3bf36 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterFactory.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterFactory.kt @@ -1,8 +1,8 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster import com.pixelized.desktop.lwa.repository.campaign.model.CharacterSheetPreview -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio.Action +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio.Action import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMTagUio import com.pixelized.shared.lwa.model.campaign.Campaign import lwacharactersheet.composeapp.generated.resources.Res @@ -18,7 +18,7 @@ class GameMasterFactory { characters: List, filter: String, tags: Map, - ): List { + ): List { val normalizedFilter = Normalizer.normalize(filter, Normalizer.Form.NFD) return characters.mapNotNull { @@ -36,7 +36,7 @@ class GameMasterFactory { character: CharacterSheetPreview, filter: String, tags: Map, - ): GMCharacterPreviewUio? { + ): GMCharacterUio? { // get the characterInstanceId from the player list corresponding to this CharacterSheet if any val characterInstanceId: Campaign.CharacterInstance.Id? = campaign.characters.keys.firstOrNull { @@ -106,9 +106,10 @@ class GameMasterFactory { ) } // return the cell UIO. - return GMCharacterPreviewUio( + return GMCharacterUio( characterSheetId = character.characterSheetId, - name = character.name, level = character.level, + name = character.name, + level = character.level, tags = previewTagsList, actions = actions, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterScreen.kt index abb8a77..419a3a8 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterScreen.kt @@ -3,12 +3,13 @@ package com.pixelized.desktop.lwa.ui.screen.gamemaster import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut -import androidx.compose.foundation.clickable +import androidx.compose.foundation.background import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.rememberDraggableState import androidx.compose.foundation.gestures.scrollBy import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize @@ -19,30 +20,40 @@ import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.CircleShape import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Scaffold import androidx.compose.material.Surface import androidx.compose.material.Text +import androidx.compose.material.TextButton import androidx.compose.material.TopAppBar +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Add import androidx.compose.runtime.Composable import androidx.compose.runtime.State import androidx.compose.runtime.collectAsState import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.LocalWindowController import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreview -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio +import com.pixelized.desktop.lwa.ui.navigation.window.destination.navigateToCharacterSheetEdit +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacter +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMTag import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMTagUio import com.pixelized.desktop.lwa.ui.theme.lwa import kotlinx.coroutines.launch import lwacharactersheet.composeapp.generated.resources.Res +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__create__title +import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__edit__title import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp +import org.jetbrains.compose.resources.getString import org.jetbrains.compose.resources.painterResource import org.koin.compose.viewmodel.koinViewModel @@ -50,6 +61,9 @@ import org.koin.compose.viewmodel.koinViewModel fun GameMasterScreen( viewModel: GameMasterViewModel = koinViewModel(), ) { + val windows = LocalWindowController.current + val scope = rememberCoroutineScope() + val characters = viewModel.characters.collectAsState() val tags = viewModel.tags.collectAsState() @@ -59,10 +73,27 @@ fun GameMasterScreen( GameMasterContent( modifier = Modifier.fillMaxSize(), filter = viewModel.filter, + onGameMaster = viewModel::onGameMaster, tags = tags, characters = characters, onTag = viewModel::onTag, onCharacterAction = viewModel::onCharacterAction, + onCharacterSheetEdit = { characterSheetId -> + scope.launch { + windows.navigateToCharacterSheetEdit( + characterId = characterSheetId, + title = getString(Res.string.character_sheet_edit__edit__title), + ) + } + }, + onCharacterSheetCreate = { + scope.launch { + windows.navigateToCharacterSheetEdit( + characterId = null, + title = getString(Res.string.character_sheet_edit__create__title), + ) + } + }, ) } } @@ -73,9 +104,12 @@ private fun GameMasterContent( filterChipsState: LazyListState = rememberLazyListState(), filter: LwaTextFieldUio, tags: State>, - characters: State>, + characters: State>, + onGameMaster: () -> Unit, onTag: (GMTagUio.TagId) -> Unit, - onCharacterAction: (String, GMCharacterPreviewUio.Action) -> Unit, + onCharacterAction: (String, GMCharacterUio.Action) -> Unit, + onCharacterSheetEdit: (String) -> Unit, + onCharacterSheetCreate: () -> Unit, ) { val scope = rememberCoroutineScope() @@ -87,6 +121,13 @@ private fun GameMasterContent( Text( text = "", ) + }, + actions = { + TextButton( + onClick = onGameMaster, + ) { + Text(text = "GameMaster") + } } ) }, @@ -94,65 +135,105 @@ private fun GameMasterContent( Column( modifier = Modifier.padding(paddingValues = paddingValues) ) { - LwaTextField( - modifier = Modifier.fillMaxWidth(), - field = filter, - trailingIcon = { - val value = filter.valueFlow.collectAsState() - AnimatedVisibility( - visible = value.value.isNotBlank(), - enter = fadeIn(), - exit = fadeOut(), + Surface( + elevation = 1.dp, + ) { + Column { + LwaTextField( + modifier = Modifier.fillMaxWidth(), + field = filter, + trailingIcon = { + val value = filter.valueFlow.collectAsState() + AnimatedVisibility( + visible = value.value.isNotBlank(), + enter = fadeIn(), + exit = fadeOut(), + ) { + IconButton( + onClick = { filter.onValueChange.invoke("") }, + ) { + Icon( + painter = painterResource(Res.drawable.ic_cancel_24dp), + tint = MaterialTheme.lwa.colorScheme.base.primary, + contentDescription = null, + ) + } + } + } + ) + LazyRow( + modifier = Modifier.draggable( + orientation = Orientation.Horizontal, + state = rememberDraggableState { delta -> + scope.launch { + filterChipsState.scrollBy(-delta) + } + }, + ), + state = filterChipsState, + contentPadding = remember { PaddingValues(all = 8.dp) }, + horizontalArrangement = Arrangement.spacedBy(space = 8.dp), ) { - IconButton( - onClick = { filter.onValueChange.invoke("") }, - ) { - Icon( - painter = painterResource(Res.drawable.ic_cancel_24dp), - tint = MaterialTheme.lwa.colorScheme.base.primary, - contentDescription = null, + items( + items = tags.value, + ) { tag -> + GMTag( + style = MaterialTheme.lwa.typography.base.body1, + tag = tag, + onTag = { onTag(tag.id) }, ) } } } - ) - LazyRow( - modifier = Modifier.draggable( - orientation = Orientation.Horizontal, - state = rememberDraggableState { delta -> - scope.launch { - filterChipsState.scrollBy(-delta) - } - }, - ), - state = filterChipsState, - contentPadding = remember { PaddingValues(all = 8.dp) }, - horizontalArrangement = Arrangement.spacedBy(space = 8.dp), - ) { - items( - items = tags.value, - ) { tag -> - GMTag( - style = MaterialTheme.lwa.typography.base.body1, - tag = tag, - onTag = { onTag(tag.id) }, - ) - } } - LazyColumn( - modifier = Modifier.weight(1f), - contentPadding = remember { PaddingValues(all = 8.dp) }, - verticalArrangement = Arrangement.spacedBy(space = 8.dp), + Box( + modifier = Modifier.fillMaxWidth().weight(1f), ) { - items( - items = characters.value, - ) { character -> - GMCharacterPreview( - modifier = Modifier.fillMaxWidth(), - character = character, - onAction = { action -> - onCharacterAction(character.characterSheetId, action) - } + LazyColumn( + modifier = Modifier.matchParentSize(), + contentPadding = remember { + PaddingValues( + start = 8.dp, + top = 8.dp, + end = 8.dp, + bottom = 8.dp + 48.dp + 8.dp, + ) + }, + verticalArrangement = Arrangement.spacedBy(space = 8.dp), + ) { + items( + items = characters.value, + key = { it.characterSheetId }, + ) { character -> + GMCharacter( + modifier = Modifier + .fillMaxWidth() + .animateItem(), + character = character, + onEdit = { + onCharacterSheetEdit(character.characterSheetId) + }, + onAction = { action -> + onCharacterAction(character.characterSheetId, action) + }, + ) + } + } + + IconButton( + modifier = Modifier + .align(alignment = Alignment.BottomEnd) + .padding(all = 8.dp) + .background( + color = MaterialTheme.lwa.colorScheme.base.primary, + shape = CircleShape, + ), + onClick = onCharacterSheetCreate, + ) { + Icon( + imageVector = Icons.Default.Add, + tint = MaterialTheme.lwa.colorScheme.base.onPrimary, + contentDescription = null, ) } } diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterViewModel.kt index dffbde7..f6cf229 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/GameMasterViewModel.kt @@ -4,8 +4,9 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository +import com.pixelized.desktop.lwa.repository.settings.SettingsRepository import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMTagUio import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMTagUio.TagId import kotlinx.coroutines.flow.MutableStateFlow @@ -20,9 +21,10 @@ import lwacharactersheet.composeapp.generated.resources.game_master__character_t import org.jetbrains.compose.resources.getString class GameMasterViewModel( - private val campaignRepository: CampaignRepository, - private val characterSheetRepository: CharacterSheetRepository, - private val gameMasterFactory: GameMasterFactory, + campaignRepository: CampaignRepository, + characterSheetRepository: CharacterSheetRepository, + private val settingsRepository: SettingsRepository, + private val factory: GameMasterFactory, private val useCase: GameMasterActionUseCase, ) : ViewModel() { @@ -63,16 +65,25 @@ class GameMasterViewModel( characterSheetRepository.characterSheetPreviewFlow, filter.valueFlow, _tags, - gameMasterFactory::convertToGMCharacterPreviewUio, + factory::convertToGMCharacterPreviewUio, ).stateIn( scope = viewModelScope, started = SharingStarted.Eagerly, initialValue = emptyList(), ) + fun onGameMaster() { + val settings = settingsRepository.settings() + settingsRepository.update( + settings = settings.copy( + isGM = settings.isGM.not(), + ) + ) + } + fun onCharacterAction( characterSheetId: String, - action: GMCharacterPreviewUio.Action, + action: GMCharacterUio.Action, ) { viewModelScope.launch { try { diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacterPreview.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacter.kt similarity index 59% rename from composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacterPreview.kt rename to composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacter.kt index bf0261d..af6637f 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacterPreview.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/gamemaster/items/GMCharacter.kt @@ -16,6 +16,7 @@ import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Edit import androidx.compose.material.icons.filled.MoreVert import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable @@ -27,7 +28,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.DpOffset import androidx.compose.ui.unit.dp -import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterPreviewUio.Action +import com.pixelized.desktop.lwa.ui.screen.gamemaster.items.GMCharacterUio.Action import com.pixelized.desktop.lwa.ui.theme.lwa import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.game_master__character_action__add_to_group @@ -36,10 +37,17 @@ import lwacharactersheet.composeapp.generated.resources.game_master__character_a import lwacharactersheet.composeapp.generated.resources.game_master__character_action__remove_from_group import lwacharactersheet.composeapp.generated.resources.game_master__character_action__remove_from_npc import lwacharactersheet.composeapp.generated.resources.game_master__character_level__label +import lwacharactersheet.composeapp.generated.resources.ic_face_24dp +import lwacharactersheet.composeapp.generated.resources.ic_face_retouching_off_24dp +import lwacharactersheet.composeapp.generated.resources.ic_group_24dp +import lwacharactersheet.composeapp.generated.resources.ic_group_off_24dp +import lwacharactersheet.composeapp.generated.resources.ic_imagesmode_24dp +import org.jetbrains.compose.resources.DrawableResource +import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.stringResource @Stable -data class GMCharacterPreviewUio( +data class GMCharacterUio( val characterSheetId: String, val name: String, val level: Int, @@ -47,21 +55,33 @@ data class GMCharacterPreviewUio( val actions: List, ) { @Stable - sealed class Action { + sealed class Action( + val icon: DrawableResource, + ) { @Stable - data object DisplayPortrait : Action() + data object DisplayPortrait : Action( + icon = Res.drawable.ic_imagesmode_24dp, + ) @Stable - data object AddToGroup : Action() + data object AddToGroup : Action( + icon = Res.drawable.ic_group_24dp, + ) @Stable - data class RemoveFromGroup(val instanceId: Int) : Action() + data class RemoveFromGroup(val instanceId: Int) : Action( + icon = Res.drawable.ic_group_off_24dp, + ) @Stable - data object AddToNpc : Action() + data object AddToNpc : Action( + icon = Res.drawable.ic_face_24dp, + ) @Stable - data class RemoveFromNpc(val instanceId: Int) : Action() + data class RemoveFromNpc(val instanceId: Int) : Action( + icon = Res.drawable.ic_face_retouching_off_24dp, + ) } } @@ -70,10 +90,11 @@ object GMCharacterPreviewDefault { } @Composable -fun GMCharacterPreview( +fun GMCharacter( modifier: Modifier = Modifier, padding: PaddingValues = GMCharacterPreviewDefault.padding, - character: GMCharacterPreviewUio, + character: GMCharacterUio, + onEdit: () -> Unit, onAction: (Action) -> Unit, ) { val layoutDirection = LocalLayoutDirection.current @@ -108,20 +129,22 @@ fun GMCharacterPreview( ), ) } - OverflowActionMenu( + MenuActions( character = character, + onEdit = onEdit, onAction = onAction, ) } Row( modifier = Modifier .padding(paddingValues = padding) - .padding(bottom = 16.dp), + .padding(bottom = 8.dp), horizontalArrangement = Arrangement.spacedBy(space = 4.dp), ) { character.tags.forEach { tag -> GMTag( style = MaterialTheme.lwa.typography.base.caption, + elevation = 4.dp, tag = tag, ) } @@ -130,10 +153,36 @@ fun GMCharacterPreview( } } +@Composable +private fun MenuActions( + modifier: Modifier = Modifier, + character: GMCharacterUio, + onEdit: () -> Unit, + onAction: (Action) -> Unit, +) { + Row( + modifier = modifier, + ) { + IconButton( + onClick = onEdit + ) { + Icon( + imageVector = Icons.Default.Edit, + tint = MaterialTheme.lwa.colorScheme.base.primary, + contentDescription = null, + ) + } + OverflowActionMenu( + character = character, + onAction = onAction, + ) + } +} + @Composable private fun OverflowActionMenu( modifier: Modifier = Modifier, - character: GMCharacterPreviewUio, + character: GMCharacterUio, onAction: (Action) -> Unit, ) { val overflowMenu = remember(character) { @@ -165,33 +214,43 @@ private fun OverflowActionMenu( onAction(action) }, ) { - Text( - style = MaterialTheme.lwa.typography.base.body1, - color = MaterialTheme.lwa.colorScheme.base.primary, - text = when (action) { - Action.DisplayPortrait -> stringResource( - Res.string.game_master__character_action__display_portrait, - ) + Row( + horizontalArrangement = Arrangement.spacedBy(space = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + painter = painterResource(action.icon), + tint = MaterialTheme.lwa.colorScheme.base.primary, + contentDescription = null, + ) + Text( + style = MaterialTheme.lwa.typography.base.body1, + color = MaterialTheme.lwa.colorScheme.base.primary, + text = when (action) { + Action.DisplayPortrait -> stringResource( + Res.string.game_master__character_action__display_portrait, + ) - Action.AddToGroup -> stringResource( - Res.string.game_master__character_action__add_to_group, - ) + Action.AddToGroup -> stringResource( + Res.string.game_master__character_action__add_to_group, + ) - Action.AddToNpc -> stringResource( - Res.string.game_master__character_action__add_to_npc, - ) + Action.AddToNpc -> stringResource( + Res.string.game_master__character_action__add_to_npc, + ) - is Action.RemoveFromGroup -> stringResource( - Res.string.game_master__character_action__remove_from_group, - action.instanceId, - ) + is Action.RemoveFromGroup -> stringResource( + Res.string.game_master__character_action__remove_from_group, + action.instanceId, + ) - is Action.RemoveFromNpc -> stringResource( - Res.string.game_master__character_action__remove_from_npc, - action.instanceId, - ) - } - ) + is Action.RemoveFromNpc -> stringResource( + Res.string.game_master__character_action__remove_from_npc, + action.instanceId, + ) + } + ) + } } } }, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/typography/LwaTypography.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/typography/LwaTypography.kt index a550f0f..f91794c 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/typography/LwaTypography.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/theme/typography/LwaTypography.kt @@ -4,12 +4,16 @@ import androidx.compose.material.Typography import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.remember +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.Shadow import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.sp +import com.pixelized.desktop.lwa.ui.theme.color.LwaColorPalette import com.pixelized.desktop.lwa.ui.theme.color.LwaColors import com.pixelized.desktop.lwa.ui.theme.typography.LwaTypography.Settings import lwacharactersheet.composeapp.generated.resources.Res @@ -22,6 +26,7 @@ data class LwaTypography( val base: Typography, val chat: Chat, val settings: Settings, + val portrait: Portrait, ) { @Stable data class Chat( @@ -36,6 +41,13 @@ data class LwaTypography( val input: TextStyle, val description: TextStyle, ) + + @Stable + data class Portrait( + val idLabel: TextStyle, + val value: TextStyle, + val max: TextStyle, + ) } @Composable @@ -90,6 +102,32 @@ fun lwaTypography( fontStyle = FontStyle.Italic, color = colors.base.onSurface.copy(alpha = 0.7f), ), + ), + portrait = LwaTypography.Portrait( + idLabel = base.caption.copy( + fontWeight = FontWeight.SemiBold, + shadow = Shadow( + color = Color.Black, + offset = Offset(x = 1f, y = 1f), + blurRadius = 2f, + ), + ), + value = base.caption.copy( + fontWeight = FontWeight.Bold, + shadow = Shadow( + color = Color.Black, + offset = Offset(x = 1f, y = 1f), + blurRadius = 2f, + ), + ), + max = base.caption.copy( + fontWeight = FontWeight.Light, + shadow = Shadow( + color = Color.Black, + offset = Offset(x = 1f, y = 1f), + blurRadius = 2f, + ), + ), ) ) } 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 eff28b5..2bc0583 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 @@ -13,6 +13,7 @@ class SettingsUseCase { autoHideDelay = 8, autoShowChat = true, autoScrollChat = true, + isAdmin = false, isGM = false, )