Add switch to the gamemaster screen + small adjustment for the UI.

This commit is contained in:
Andres Gomez, Thomas (ITDV RL) 2025-03-19 09:48:13 +01:00
parent 50ed975913
commit edbb508f6a
6 changed files with 76 additions and 15 deletions

View file

@ -210,6 +210,8 @@
<string name="level_up__character_level_description">Passage du niveau %1$d &#x25B8; %2$d</string> <string name="level_up__character_level_description">Passage du niveau %1$d &#x25B8; %2$d</string>
<string name="level_up__skill_level">niv : %1$d -</string> <string name="level_up__skill_level">niv : %1$d -</string>
<string name="game_master__title">Admin</string>
<string name="game_master__action">GameMaster</string>
<string name="game_master__character_level__label">niv: %1$d</string> <string name="game_master__character_level__label">niv: %1$d</string>
<string name="game_master__character_tag__character_search">Joueur</string> <string name="game_master__character_tag__character_search">Joueur</string>
<string name="game_master__character_tag__character_label">Joueur-%1$d</string> <string name="game_master__character_tag__character_label">Joueur-%1$d</string>

View file

@ -9,6 +9,7 @@ import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -36,17 +37,16 @@ class DataSyncViewModel(
networkRepository.status networkRepository.status
.filter { status -> status == NetworkRepository.Status.CONNECTED } .filter { status -> status == NetworkRepository.Status.CONNECTED }
.onEach { campaignRepository.campaign(update = true) } .onEach {
.launchIn(this) campaignRepository.campaign(update = true)
characterRepository.updateCharacterPreviews()
networkRepository.status }
.filter { status -> status == NetworkRepository.Status.CONNECTED }
.onEach { characterRepository.updateCharacterPreviews() }
.launchIn(this) .launchIn(this)
networkRepository.status networkRepository.status
.filter { status -> status == NetworkRepository.Status.CONNECTED } .filter { status -> status == NetworkRepository.Status.CONNECTED }
.combine(campaignRepository.campaignFlow) { _, campaign: Campaign -> campaign } .combine(campaignRepository.campaignFlow) { _, campaign: Campaign -> campaign }
.distinctUntilChanged()
.onEach { campaign -> .onEach { campaign ->
(campaign.characters.keys + campaign.npcs.keys).forEach { id -> (campaign.characters.keys + campaign.npcs.keys).forEach { id ->
characterRepository.characterDetail( characterRepository.characterDetail(

View file

@ -4,6 +4,7 @@ import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState import androidx.compose.foundation.gestures.rememberDraggableState
@ -12,6 +13,8 @@ import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
@ -26,8 +29,8 @@ import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Scaffold import androidx.compose.material.Scaffold
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Switch
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
@ -38,6 +41,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.LocalWindowController import com.pixelized.desktop.lwa.LocalWindowController
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField
@ -52,9 +56,12 @@ import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet_edit__create__title 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.character_sheet_edit__edit__title
import lwacharactersheet.composeapp.generated.resources.game_master__action
import lwacharactersheet.composeapp.generated.resources.game_master__title
import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp
import org.jetbrains.compose.resources.getString import org.jetbrains.compose.resources.getString
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
@Composable @Composable
@ -65,6 +72,7 @@ fun GameMasterScreen(
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val characters = viewModel.characters.collectAsState() val characters = viewModel.characters.collectAsState()
val gameMaster = viewModel.gameMaster.collectAsState()
val tags = viewModel.tags.collectAsState() val tags = viewModel.tags.collectAsState()
Surface( Surface(
@ -73,10 +81,11 @@ fun GameMasterScreen(
GameMasterContent( GameMasterContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
filter = viewModel.filter, filter = viewModel.filter,
onGameMaster = viewModel::onGameMaster,
tags = tags, tags = tags,
gameMaster = gameMaster,
characters = characters, characters = characters,
onTag = viewModel::onTag, onTag = viewModel::onTag,
onGameMaster = viewModel::onGameMaster,
onCharacterAction = viewModel::onCharacterAction, onCharacterAction = viewModel::onCharacterAction,
onCharacterSheetEdit = { characterSheetId -> onCharacterSheetEdit = { characterSheetId ->
scope.launch { scope.launch {
@ -104,8 +113,9 @@ private fun GameMasterContent(
filterChipsState: LazyListState = rememberLazyListState(), filterChipsState: LazyListState = rememberLazyListState(),
filter: LwaTextFieldUio, filter: LwaTextFieldUio,
tags: State<List<GMTagUio>>, tags: State<List<GMTagUio>>,
gameMaster: State<Boolean>,
characters: State<List<GMCharacterUio>>, characters: State<List<GMCharacterUio>>,
onGameMaster: () -> Unit, onGameMaster: (Boolean) -> Unit,
onTag: (GMTagUio.TagId) -> Unit, onTag: (GMTagUio.TagId) -> Unit,
onCharacterAction: (String, GMCharacterUio.Action) -> Unit, onCharacterAction: (String, GMCharacterUio.Action) -> Unit,
onCharacterSheetEdit: (String) -> Unit, onCharacterSheetEdit: (String) -> Unit,
@ -119,14 +129,28 @@ private fun GameMasterContent(
TopAppBar( TopAppBar(
title = { title = {
Text( Text(
text = "", text = stringResource(Res.string.game_master__title),
) )
}, },
actions = { actions = {
TextButton( Row(
onClick = onGameMaster, modifier = Modifier
.clip(shape = CircleShape)
.clickable { onGameMaster(gameMaster.value.not()) }
.padding(all = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(space = 4.dp)
) { ) {
Text(text = "GameMaster") Text(
color = MaterialTheme.lwa.colorScheme.base.primary,
style = MaterialTheme.typography.caption,
text = stringResource(Res.string.game_master__action),
)
Switch(
checked = gameMaster.value,
colors = MaterialTheme.lwa.colorScheme.component.switch,
onCheckedChange = null,
)
} }
} }
) )

View file

@ -13,6 +13,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
@ -72,11 +73,19 @@ class GameMasterViewModel(
initialValue = emptyList(), initialValue = emptyList(),
) )
fun onGameMaster() { val gameMaster = settingsRepository.settingsFlow()
.map { it.isGameMaster ?: false }
.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = false,
)
fun onGameMaster(value: Boolean) {
val settings = settingsRepository.settings() val settings = settingsRepository.settings()
settingsRepository.update( settingsRepository.update(
settings = settings.copy( settings = settings.copy(
isGameMaster = (settings.isGameMaster ?: false).not(), isGameMaster = value,
) )
) )
} }

View file

@ -1,6 +1,7 @@
package com.pixelized.desktop.lwa.ui.theme.color package com.pixelized.desktop.lwa.ui.theme.color
import androidx.compose.material.Colors import androidx.compose.material.Colors
import androidx.compose.material.SwitchColors
import androidx.compose.material.darkColors import androidx.compose.material.darkColors
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.runtime.ReadOnlyComposable
@ -10,16 +11,23 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.graphics.compositeOver
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.color.component.lwaSwitch
import kotlin.math.ln import kotlin.math.ln
@Stable @Stable
data class LwaColors( data class LwaColors(
val base: Colors, val base: Colors,
val component: Component,
val elevated: Elevated, val elevated: Elevated,
val portrait: Portrait, val portrait: Portrait,
val portraitBackgroundBrush: Brush, val portraitBackgroundBrush: Brush,
val chat: Chat, val chat: Chat,
) { ) {
@Stable
data class Component(
val switch: SwitchColors,
)
@Stable @Stable
data class Elevated( data class Elevated(
val base1dp: Color, val base1dp: Color,
@ -72,6 +80,9 @@ fun darkLwaColorTheme(
elevation = 4.dp, elevation = 4.dp,
), ),
), ),
component: LwaColors.Component = LwaColors.Component(
switch = lwaSwitch(base = base),
),
portraitBackgroundBrush: Brush = Brush.verticalGradient( portraitBackgroundBrush: Brush = Brush.verticalGradient(
listOf( listOf(
elevated.base1dp.copy(alpha = 0.0f), elevated.base1dp.copy(alpha = 0.0f),
@ -96,6 +107,7 @@ fun darkLwaColorTheme(
), ),
): LwaColors = LwaColors( ): LwaColors = LwaColors(
base = base, base = base,
component = component,
elevated = elevated, elevated = elevated,
portrait = portrait, portrait = portrait,
portraitBackgroundBrush = portraitBackgroundBrush, portraitBackgroundBrush = portraitBackgroundBrush,

View file

@ -0,0 +1,14 @@
package com.pixelized.desktop.lwa.ui.theme.color.component
import androidx.compose.material.Colors
import androidx.compose.material.SwitchDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
@Composable
@Stable
fun lwaSwitch(
base: Colors
) = SwitchDefaults.colors(
checkedThumbColor = base.primary,
)