Last commit for the settings pages.

This commit is contained in:
Thomas Andres Gomez 2025-03-05 18:40:17 +01:00
parent f60a58f71e
commit 84515e6d57
20 changed files with 450 additions and 71 deletions

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,880 L340,740l56,-56 44,43v-247h80v247l44,-43 56,56L480,880ZM240,720 L100,580l56,-56 44,43v-247h80v247l44,-43 56,56 -140,140ZM720,720L580,580l56,-56 44,43v-247h80v247l44,-43 56,56 -140,140ZM80,440v-240q0,-33 23.5,-56.5T160,120h640q33,0 56.5,23.5T880,200v240h-80v-240L160,200v240L80,440Z"
android:fillColor="#5f6368"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M640,700q25,0 42.5,-17.5T700,640q0,-25 -17.5,-42.5T640,580q-25,0 -42.5,17.5T580,640q0,25 17.5,42.5T640,700ZM480,540q25,0 42.5,-17.5T540,480q0,-25 -17.5,-42.5T480,420q-25,0 -42.5,17.5T420,480q0,25 17.5,42.5T480,540ZM320,380q25,0 42.5,-17.5T380,320q0,-25 -17.5,-42.5T320,260q-25,0 -42.5,17.5T260,320q0,25 17.5,42.5T320,380ZM200,840q-33,0 -56.5,-23.5T120,760v-560q0,-33 23.5,-56.5T200,120h560q33,0 56.5,23.5T840,200v560q0,33 -23.5,56.5T760,840L200,840ZM200,760h560v-560L200,200v560ZM200,200v560,-560Z"
android:fillColor="#5f6368"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M360,120v-80h240v80L360,120ZM440,560h80v-240h-80v240ZM480,880q-74,0 -139.5,-28.5T226,774q-49,-49 -77.5,-114.5T120,520q0,-74 28.5,-139.5T226,266q49,-49 114.5,-77.5T480,160q62,0 119,20t107,58l56,-56 56,56 -56,56q38,50 58,107t20,119q0,74 -28.5,139.5T734,774q-49,49 -114.5,77.5T480,880ZM480,800q116,0 198,-82t82,-198q0,-116 -82,-198t-198,-82q-116,0 -198,82t-82,198q0,116 82,198t198,82ZM480,520Z"
android:fillColor="#5f6368"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="M480,640q75,0 127.5,-52.5T660,460q0,-75 -52.5,-127.5T480,280q-75,0 -127.5,52.5T300,460q0,75 52.5,127.5T480,640ZM480,568q-45,0 -76.5,-31.5T372,460q0,-45 31.5,-76.5T480,352q45,0 76.5,31.5T588,460q0,45 -31.5,76.5T480,568ZM480,760q-146,0 -266,-81.5T40,460q54,-137 174,-218.5T480,160q146,0 266,81.5T920,460q-54,137 -174,218.5T480,760ZM480,460ZM480,680q113,0 207.5,-59.5T832,460q-50,-101 -144.5,-160.5T480,240q-113,0 -207.5,59.5T128,460q50,101 144.5,160.5T480,680Z"
android:fillColor="#5f6368"/>
</vector>

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:pathData="m644,532 l-58,-58q9,-47 -27,-88t-93,-32l-58,-58q17,-8 34.5,-12t37.5,-4q75,0 127.5,52.5T660,460q0,20 -4,37.5T644,532ZM772,658 L714,602q38,-29 67.5,-63.5T832,460q-50,-101 -143.5,-160.5T480,240q-29,0 -57,4t-55,12l-62,-62q41,-17 84,-25.5t90,-8.5q151,0 269,83.5T920,460q-23,59 -60.5,109.5T772,658ZM792,904L624,738q-35,11 -70.5,16.5T480,760q-151,0 -269,-83.5T40,460q21,-53 53,-98.5t73,-81.5L56,168l56,-56 736,736 -56,56ZM222,336q-29,26 -53,57t-41,67q50,101 143.5,160.5T480,680q20,0 39,-2.5t39,-5.5l-36,-38q-11,3 -21,4.5t-21,1.5q-75,0 -127.5,-52.5T300,460q0,-11 1.5,-21t4.5,-21l-84,-82ZM541,429ZM390,504Z"
android:fillColor="#5f6368"/>
</vector>

View file

@ -158,8 +158,24 @@
<string name="roll_history__item__throw">lance</string>
<string name="roll_history__item__difficulty">Difficulté</string>
<string name="chat__diminished_change">%1$s passe à %2$d d\'état diminuée</string>
<string name="chat__diminished_change">%1$s passe à %2$d d'état diminuée</string>
<string name="chat__characteristic_change">%1$s passe à %2$d %3$s</string>
<string name="chat__characteristic__hp">Hp</string>
<string name="chat__characteristic__pp">Pp</string>
<string name="settings__title">Paramètres de l'application</string>
<string name="settings__reset_action">Paramètres par défault</string>
<string name="settings__player_portrait__section">Portrait joueur</string>
<string name="settings__player_portrait__dyn_dice_tile">Dés dynamiques</string>
<string name="settings__player_portrait__dyn_dice_description">Affiche un dé à côté du portrait d'un personnage lorsqu'un jet est fait par ce dernier.</string>
<string name="settings__chat_log__section">Chatlog options</string>
<string name="settings__chat_log__auto_show_title">Afficher automatiquement le chat</string>
<string name="settings__chat_log__auto_show_description">Affiche automatiquement le chat lors de la réception d'un message</string>
<string name="settings__chat_log__auto_hide_title">Cacher automatiquement le chat</string>
<string name="settings__chat_log__auto_hide_description">Cache automatiquement le chat au bout d'un certain temps</string>
<string name="settings__chat_log__auto_hide_delay_title">Délai pour cacher le chat</string>
<string name="settings__chat_log__auto_hide_delay_description">Délai après lequel le chat disparaît</string>
<string name="settings__chat_log__auto_scroll_title">Défilement automatique</string>
<string name="settings__chat_log__auto_scroll_description">Défilement automatique du chat vers le dernier message reçu lors de la réception de ce dernier.</string>
</resources>

View file

@ -18,6 +18,7 @@ class SettingsFactory(
playerName = settings.playerName,
dynamicDice = settings.dynamicDice,
autoHideChat = settings.autoHideChat,
autoHideDelay = settings.autoHideDelay,
autoShowChat = settings.autoShowChat,
autoScrollChat = settings.autoScrollChat,
)
@ -41,6 +42,7 @@ class SettingsFactory(
playerName = json.playerName ?: default.playerName,
dynamicDice = json.dynamicDice ?: default.dynamicDice,
autoHideChat = json.autoHideChat ?: default.autoHideChat,
autoHideDelay = json.autoHideDelay ?: default.autoHideDelay,
autoShowChat = json.autoShowChat ?: default.autoShowChat,
autoScrollChat = json.autoScrollChat ?: default.autoScrollChat,
)

View file

@ -6,6 +6,7 @@ data class Settings(
val playerName: String,
val dynamicDice: Boolean,
val autoHideChat: Boolean,
val autoHideDelay: Int,
val autoShowChat: Boolean,
val autoScrollChat: Boolean,
) {

View file

@ -9,6 +9,7 @@ data class SettingsJsonV1(
val playerName: String?,
val dynamicDice: Boolean?,
val autoHideChat: Boolean?,
val autoHideDelay: Int?,
val autoShowChat: Boolean?,
val autoScrollChat: Boolean?,
) : SettingsJson

View file

@ -42,10 +42,18 @@ class CampaignChatViewModel(
)
suspend fun displayChat() {
chatAnimatedVisibility.animateTo(1f)
chatAnimatedVisibility.animateTo(
targetValue = 1f,
)
}
suspend fun hideChat() {
chatAnimatedVisibility.animateTo(0f, animationSpec = tween(2000, delayMillis = 8000))
chatAnimatedVisibility.animateTo(
targetValue = 0f,
animationSpec = tween(
durationMillis = 2000,
delayMillis = settings.value.autoHideDelay * 1000,
)
)
}
}

View file

@ -12,6 +12,7 @@ import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
@ -24,6 +25,7 @@ import java.text.Collator
class PlayerRibbonViewModel(
private val rollHistoryRepository: RollHistoryRepository,
private val settingsRepository: SettingsRepository,
characterRepository: CharacterSheetRepository,
alterationRepository: AlterationRepository,
private val ribbonFactory: PlayerRibbonFactory,
@ -68,12 +70,14 @@ class PlayerRibbonViewModel(
val state = rolls.getOrPut(characterSheetId) { mutableStateOf(null) }
LaunchedEffect(characterSheetId) {
rollHistoryRepository.rolls.collect { roll ->
if (roll.characterId == characterSheetId) {
state.value = PlayerPortraitRollUio(
characterId = characterSheetId,
value = roll.rollValue,
label = roll.resultLabel?.split(" ")?.joinToString(separator = "\n") { it }
)
if (settingsRepository.settings().dynamicDice) {
if (roll.characterId == characterSheetId) {
state.value = PlayerPortraitRollUio(
characterId = characterSheetId,
value = roll.rollValue,
label = roll.resultLabel?.split(" ")?.joinToString(separator = "\n") { it }
)
}
}
}
}

View file

@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.ui.screen.settings
import androidx.compose.foundation.ScrollState
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
@ -12,21 +13,38 @@ import androidx.compose.material.IconButton
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.automirrored.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.SettingsDestination
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingItemUio
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingNumberItem
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingNumberItemUio
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingSection
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingSectionUio
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingToggleItem
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingToggleItemUio
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.settings__reset_action
import lwacharactersheet.composeapp.generated.resources.settings__title
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
object SettingsScreenDefault {
val margin: PaddingValues = PaddingValues(horizontal = 16.dp)
val padding: PaddingValues = PaddingValues(start = 16.dp, top = 8.dp, end = 8.dp, bottom = 8.dp)
}
@Composable
fun SettingsScreen(
@ -34,13 +52,25 @@ fun SettingsScreen(
) {
val screen = LocalScreenController.current
KeyHandler {
when {
it.type == KeyEventType.KeyUp && it.key == Key.Escape -> {
screen.popBackStack(route = SettingsDestination.baseRoute(), inclusive = true)
true
}
else -> false
}
}
Surface {
SettingsContent(
modifier = Modifier.fillMaxSize(),
items = viewModel.items,
onBack = {
screen.popBackStack()
screen.popBackStack(route = SettingsDestination.baseRoute(), inclusive = true)
},
onReset = viewModel::onReset
)
}
}
@ -52,13 +82,14 @@ private fun SettingsContent(
spacing: Dp = 8.dp,
items: List<SettingItemUio>,
onBack: () -> Unit,
onReset: () -> Unit,
) {
Scaffold(
modifier = modifier,
topBar = {
TopAppBar(
title = {
Text(text = "Paramètres de l\'application")
Text(text = stringResource(Res.string.settings__title))
},
navigationIcon = {
IconButton(
@ -69,7 +100,14 @@ private fun SettingsContent(
contentDescription = null,
)
}
}
},
actions = {
TextButton(
onClick = onReset,
) {
Text(text = stringResource(Res.string.settings__reset_action))
}
},
)
},
content = { paddingValues ->
@ -81,17 +119,12 @@ private fun SettingsContent(
) {
items.forEach {
when (it) {
is SettingSectionUio -> {
SettingSection(item = it)
}
is SettingToggleItemUio -> {
SettingToggleItem(item = it)
}
is SettingSectionUio -> SettingSection(item = it)
is SettingToggleItemUio -> SettingToggleItem(item = it)
is SettingNumberItemUio -> SettingNumberItem(item = it)
}
}
}
}
)
}

View file

@ -5,51 +5,90 @@ import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.desktop.lwa.repository.settings.SettingsRepository
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingNumberItemUio
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingSectionUio
import com.pixelized.desktop.lwa.ui.screen.settings.composable.SettingToggleItemUio
import com.pixelized.desktop.lwa.usecase.SettingsUseCase
import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_fan_focus_24dp
import lwacharactersheet.composeapp.generated.resources.ic_ifl_24dp
import lwacharactersheet.composeapp.generated.resources.ic_timer_24dp
import lwacharactersheet.composeapp.generated.resources.ic_visibility_24dp
import lwacharactersheet.composeapp.generated.resources.ic_visibility_off_24dp
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_delay_description
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_delay_title
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_description
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_hide_title
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_scroll_description
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_scroll_title
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_show_description
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto_show_title
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__section
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_description
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_tile
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__section
class SettingsViewModel(
private val settingsRepository: SettingsRepository,
private val settingsUseCase: SettingsUseCase,
) : ViewModel() {
private val settings = settingsRepository.settingsFlow()
private val states = hashMapOf<String, MutableState<Boolean>>()
private val booleanStates = hashMapOf<String, MutableState<Boolean>>()
private val intStates = hashMapOf<String, MutableState<Int>>()
val items = listOf(
SettingSectionUio(
title = "Portrait joueurs."
title = Res.string.settings__player_portrait__section,
),
SettingToggleItemUio(
title = "Dés dynamiques",
description = "Affiche un dés à côté du portrait d'un personnage lorsqu\'un jet est fait par ce dernier.",
checked = states.dynamicDice,
icon = Res.drawable.ic_ifl_24dp,
title = Res.string.settings__player_portrait__dyn_dice_tile,
description = Res.string.settings__player_portrait__dyn_dice_description,
checked = booleanStates.dynamicDice,
onToggle = {
settingsRepository.update(settings = settings.value.copy(dynamicDice = it))
},
),
SettingSectionUio(
title = "Chatlog options."
title = Res.string.settings__chat_log__section,
),
SettingToggleItemUio(
title = "Afficher automatiquement",
description = "Affiche automatiquement le chat lors de la réception d'un message.",
checked = states.autoShowChat,
icon = Res.drawable.ic_visibility_24dp,
title = Res.string.settings__chat_log__auto_show_title,
description = Res.string.settings__chat_log__auto_show_description,
checked = booleanStates.autoShowChat,
onToggle = {
settingsRepository.update(settings = settings.value.copy(autoShowChat = it))
},
),
SettingToggleItemUio(
title = "Cacher automatiquement",
description = "Cache automatiquement le chat au bout d'un certain temps.",
checked = states.autoHideChat,
icon = Res.drawable.ic_visibility_off_24dp,
title = Res.string.settings__chat_log__auto_hide_title,
description = Res.string.settings__chat_log__auto_hide_description,
checked = booleanStates.autoHideChat,
onToggle = {
settingsRepository.update(settings = settings.value.copy(autoHideChat = it))
},
),
SettingNumberItemUio(
icon = Res.drawable.ic_timer_24dp,
title = Res.string.settings__chat_log__auto_hide_delay_title,
description = Res.string.settings__chat_log__auto_hide_delay_description,
enable = booleanStates.autoHideChat,
value = intStates.autoHideDelay,
onValueChange = {
if (it in 0..999) {
settingsRepository.update(settings = settings.value.copy(autoHideDelay = it))
}
}
),
SettingToggleItemUio(
title = "Défilement automatique",
description = "Défilement automatique de chat vers le dernier message reçu lors de la réception de ce dernier.",
checked = states.autoScrollChat,
icon = Res.drawable.ic_fan_focus_24dp,
title = Res.string.settings__chat_log__auto_scroll_title,
description = Res.string.settings__chat_log__auto_scroll_description,
checked = booleanStates.autoScrollChat,
onToggle = {
settingsRepository.update(settings = settings.value.copy(autoScrollChat = it))
},
@ -59,14 +98,19 @@ class SettingsViewModel(
init {
viewModelScope.launch {
settingsRepository.settingsFlow().collect { settings ->
states.dynamicDice.value = settings.dynamicDice
states.autoShowChat.value = settings.autoShowChat
states.autoHideChat.value = settings.autoHideChat
states.autoScrollChat.value = settings.autoScrollChat
booleanStates.dynamicDice.value = settings.dynamicDice
booleanStates.autoShowChat.value = settings.autoShowChat
booleanStates.autoHideChat.value = settings.autoHideChat
intStates.autoHideDelay.value = settings.autoHideDelay
booleanStates.autoScrollChat.value = settings.autoScrollChat
}
}
}
fun onReset() {
settingsRepository.update(settings = settingsUseCase.defaultSettings())
}
private val HashMap<String, MutableState<Boolean>>.dynamicDice
get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.dynamicDice) }
@ -76,6 +120,9 @@ class SettingsViewModel(
private val HashMap<String, MutableState<Boolean>>.autoHideChat
get() = getOrPut("AUTO_HIDE_CHAT") { mutableStateOf(settings.value.autoHideChat) }
private val HashMap<String, MutableState<Int>>.autoHideDelay
get() = getOrPut("AUTO_HIDE_DELAY") { mutableStateOf(settings.value.autoHideDelay) }
private val HashMap<String, MutableState<Boolean>>.autoScrollChat
get() = getOrPut("AUTO_SCROLL_CHAT") { mutableStateOf(settings.value.autoScrollChat) }
}

View file

@ -0,0 +1,138 @@
package com.pixelized.desktop.lwa.ui.screen.settings.composable
import androidx.compose.foundation.background
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.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsScreenDefault
import com.pixelized.desktop.lwa.ui.theme.lwa
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
@Stable
data class SettingNumberItemUio(
val icon: DrawableResource,
val title: StringResource,
val description: StringResource,
val enable: State<Boolean>,
val value: State<Int>,
val onValueChange: (Int) -> Unit,
) : SettingItemUio
@Composable
fun SettingNumberItem(
modifier: Modifier = Modifier,
margin: PaddingValues = SettingsScreenDefault.margin,
padding: PaddingValues = SettingsScreenDefault.padding,
spacing: DpSize = DpSize(width = 16.dp, height = 8.dp),
item: SettingNumberItemUio,
) {
val colorScheme = MaterialTheme.lwa.colorScheme
Surface(
modifier = modifier.padding(paddingValues = margin),
shape = MaterialTheme.lwa.shapes.settings,
elevation = 1.dp,
) {
Row(
modifier = Modifier.padding(paddingValues = padding),
horizontalArrangement = Arrangement.spacedBy(space = spacing.width),
verticalAlignment = Alignment.CenterVertically,
) {
Icon(
modifier = Modifier.size(size = 24.dp),
painter = painterResource(item.icon),
contentDescription = null,
)
Column(
modifier = Modifier.weight(weight = 1f),
verticalArrangement = Arrangement.spacedBy(space = spacing.height),
) {
Text(
style = MaterialTheme.lwa.typography.settings.title,
maxLines = 1,
text = stringResource(resource = item.title),
)
Text(
style = MaterialTheme.lwa.typography.settings.description,
fontStyle = FontStyle.Italic,
text = stringResource(resource = item.description),
)
}
Column(
modifier = Modifier.padding(end = 8.dp),
verticalArrangement = Arrangement.spacedBy(space = 4.dp),
) {
val focused = remember {
mutableStateOf(false)
}
val textColor = remember(item) {
derivedStateOf {
when (item.enable.value) {
true -> colorScheme.base.primary
else -> colorScheme.base.onSurface.copy(alpha = 0.3f)
}
}
}
val borderColor = remember(item, focused) {
derivedStateOf {
when (focused.value) {
true -> colorScheme.base.primary
else -> colorScheme.base.onSurface.copy(alpha = 0.3f)
}
}
}
BasicTextField(
modifier = Modifier
.onFocusChanged { focused.value = it.isFocused }
.width(width = 44.dp)
.padding(horizontal = 2.dp),
textStyle = MaterialTheme.lwa.typography.settings.input.copy(
color = textColor.value,
),
cursorBrush = SolidColor(MaterialTheme.colors.primary),
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done),
singleLine = true,
enabled = item.enable.value,
value = "${item.value.value}",
onValueChange = { item.onValueChange(it.toIntOrNull() ?: 0) },
)
Box(
modifier = Modifier
.background(color = borderColor.value)
.size(width = 48.dp, height = 2.dp),
)
}
}
}
}

View file

@ -8,23 +8,26 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsScreenDefault
import com.pixelized.desktop.lwa.ui.theme.lwa
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource
@Stable
data class SettingSectionUio(
val title: String,
val title: StringResource,
) : SettingItemUio
@Composable
fun SettingSection(
modifier: Modifier = Modifier,
padding: PaddingValues = PaddingValues(start = 16.dp, top = 32.dp, end = 16.dp),
padding: PaddingValues = PaddingValues(start = 16.dp, top = 32.dp, end = 16.dp, bottom = 16.dp),
item: SettingSectionUio,
) {
Text(
modifier = modifier.padding(paddingValues = padding),
style = MaterialTheme.lwa.typography.base.h6,
style = MaterialTheme.lwa.typography.settings.section,
maxLines = 1,
text = item.title,
text = stringResource(resource = item.title),
)
}

View file

@ -5,23 +5,34 @@ import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Switch
import androidx.compose.material.SwitchDefaults
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.screen.settings.SettingsScreenDefault
import com.pixelized.desktop.lwa.ui.theme.lwa
import org.jetbrains.compose.resources.DrawableResource
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource
@Stable
data class SettingToggleItemUio(
val title: String,
val description: String,
val icon: DrawableResource,
val title: StringResource,
val description: StringResource,
val checked: State<Boolean>,
val onToggle: (Boolean) -> Unit,
) : SettingItemUio
@ -29,36 +40,49 @@ data class SettingToggleItemUio(
@Composable
fun SettingToggleItem(
modifier: Modifier = Modifier,
padding: PaddingValues = PaddingValues(start = 16.dp, top = 8.dp, end = 16.dp),
spacing: Dp = 8.dp,
margin: PaddingValues = SettingsScreenDefault.margin,
padding: PaddingValues = SettingsScreenDefault.padding,
spacing: DpSize = DpSize(width = 16.dp, height = 8.dp),
item: SettingToggleItemUio,
) {
Row(
modifier = modifier.padding(paddingValues = padding),
horizontalArrangement = Arrangement.spacedBy(space = spacing),
Surface(
modifier = modifier.padding(paddingValues = margin),
shape = MaterialTheme.lwa.shapes.settings,
elevation = 1.dp,
) {
Column(
modifier = Modifier.weight(weight = 1f),
verticalArrangement = Arrangement.spacedBy(space = spacing),
Row(
modifier = Modifier.padding(paddingValues = padding),
horizontalArrangement = Arrangement.spacedBy(space = spacing.width),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
style = MaterialTheme.lwa.typography.base.body1,
maxLines = 1,
text = item.title,
Icon(
modifier = Modifier.size(size = 24.dp),
painter = painterResource(item.icon),
contentDescription = null,
)
Text(
style = MaterialTheme.lwa.typography.base.caption,
fontStyle = FontStyle.Italic,
text = item.description,
Column(
modifier = Modifier.weight(weight = 1f),
verticalArrangement = Arrangement.spacedBy(space = spacing.height),
) {
Text(
style = MaterialTheme.lwa.typography.settings.title,
maxLines = 1,
text = stringResource(resource = item.title),
)
Text(
style = MaterialTheme.lwa.typography.settings.description,
fontStyle = FontStyle.Italic,
text = stringResource(resource = item.description),
)
}
Switch(
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.lwa.colorScheme.base.primary,
),
onCheckedChange = item.onToggle,
checked = item.checked.value
)
}
Switch(
colors = SwitchDefaults.colors(
checkedThumbColor = MaterialTheme.lwa.colorScheme.base.primary,
),
onCheckedChange = item.onToggle,
checked = item.checked.value
)
}
}

View file

@ -8,6 +8,8 @@ import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.remember
import com.pixelized.desktop.lwa.ui.theme.color.LwaColors
import com.pixelized.desktop.lwa.ui.theme.color.darkLwaColorTheme
import com.pixelized.desktop.lwa.ui.theme.shapes.LwaShapes
import com.pixelized.desktop.lwa.ui.theme.shapes.lwaShapes
import com.pixelized.desktop.lwa.ui.theme.typography.LwaTypography
import com.pixelized.desktop.lwa.ui.theme.typography.lwaTypography
@ -24,6 +26,7 @@ val MaterialTheme.lwa: LwaTheme
data class LwaTheme(
val colorScheme: LwaColors,
val typography: LwaTypography,
val shapes: LwaShapes,
)
@Composable
@ -32,11 +35,13 @@ fun LwaTheme(
) {
val lwaColors = darkLwaColorTheme()
val lwaTypography = lwaTypography(colors = lwaColors)
val lwaShapes = lwaShapes()
val theme = remember {
LwaTheme(
colorScheme = lwaColors,
typography = lwaTypography,
shapes = lwaShapes,
)
}

View file

@ -0,0 +1,23 @@
package com.pixelized.desktop.lwa.ui.theme.shapes
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.Shape
import androidx.compose.ui.unit.dp
@Stable
data class LwaShapes(
val settings: Shape,
)
@Stable
@Composable
fun lwaShapes(
settings: Shape = RoundedCornerShape(8.dp),
): LwaShapes = remember {
LwaShapes(
settings = settings,
)
}

View file

@ -6,9 +6,12 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.remember
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.LwaColors
import com.pixelized.desktop.lwa.ui.theme.typography.LwaTypography.Settings
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.consola_mono_bold
import lwacharactersheet.composeapp.generated.resources.consola_mono_book
@ -18,12 +21,21 @@ import org.jetbrains.compose.resources.Font
data class LwaTypography(
val base: Typography,
val chat: Chat,
val settings: Settings,
) {
@Stable
data class Chat(
val timestamp: TextStyle,
val text: TextStyle,
)
@Stable
data class Settings(
val section: TextStyle,
val title: TextStyle,
val input: TextStyle,
val description: TextStyle,
)
}
@Composable
@ -62,6 +74,22 @@ fun lwaTypography(
letterSpacing = 0.4.sp,
color = colors.chat.text,
),
),
settings = Settings(
section = base.h6,
title = base.body1.copy(
fontWeight = FontWeight.SemiBold,
),
input = base.body1.copy(
fontWeight = FontWeight.SemiBold,
fontSize = 18.sp,
lineHeight = 26.sp,
textAlign = TextAlign.End,
),
description = base.caption.copy(
fontStyle = FontStyle.Italic,
color = colors.base.onSurface.copy(alpha = 0.7f),
),
)
)
}

View file

@ -10,6 +10,7 @@ class SettingsUseCase {
playerName = "",
dynamicDice = true,
autoHideChat = true,
autoHideDelay = 8,
autoShowChat = true,
autoScrollChat = true,
)