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,
)