diff --git a/composeApp/src/commonMain/composeResources/values/strings.xml b/composeApp/src/commonMain/composeResources/values/strings.xml
index c070d7e..5f5b95b 100644
--- a/composeApp/src/commonMain/composeResources/values/strings.xml
+++ b/composeApp/src/commonMain/composeResources/values/strings.xml
@@ -262,6 +262,8 @@
Portrait joueur
Dés dynamiques
Affiche un dé à côté du portrait d'un personnage lorsqu'un jet est fait par ce dernier.
+ Délai pour les Dés dynamiques
+ Délai après lequel les dés dynamiques disparaissent.
Chatlog options
Afficher automatiquement le chat
Affiche automatiquement le chat lors de la réception d'un message
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 9852842..8924ff2 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
@@ -17,6 +17,7 @@ class SettingsFactory(
port = settings.network.port,
playerName = settings.playerName,
dynamicDice = settings.portrait.dynamicDice,
+ dynamicDiceDelay = settings.portrait.dynamicDiceDelay,
autoHideChat = settings.chat.autoHideChat,
autoHideDelay = settings.chat.autoHideDelay,
autoShowChat = settings.chat.autoShowChat,
@@ -47,6 +48,7 @@ class SettingsFactory(
),
portrait = Settings.Portrait(
dynamicDice = json.dynamicDice ?: default.portrait.dynamicDice,
+ dynamicDiceDelay = json.dynamicDiceDelay ?: default.portrait.dynamicDiceDelay,
),
chat = Settings.Chat(
autoHideChat = json.autoHideChat ?: default.chat.autoHideChat,
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 4dcec1d..80fc9ee 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
@@ -10,6 +10,7 @@ data class Settings(
) {
data class Portrait(
val dynamicDice: Boolean,
+ val dynamicDiceDelay: Int,
)
data class Chat(
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 386314f..1f942d4 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
@@ -8,6 +8,7 @@ data class SettingsJsonV1(
val port: Int?,
val playerName: String?,
val dynamicDice: Boolean?,
+ val dynamicDiceDelay: Int?,
val autoHideChat: Boolean?,
val autoHideDelay: Int?,
val autoShowChat: Boolean?,
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 78fab0b..36f0bca 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
@@ -136,6 +136,8 @@ abstract class CharacterRibbonViewModel(
) { settings, roll ->
if (settings.portrait.dynamicDice && characterSheetId == roll.characterSheetId) {
state.value = CharacterRibbonRollUio(
+ rollId = roll.uuid,
+ hideDelay = settings.portrait.dynamicDiceDelay,
characterSheetId = characterSheetId,
value = roll.rollValue,
tint = when (roll.critical) {
@@ -153,10 +155,4 @@ abstract class CharacterRibbonViewModel(
return state
}
-
- fun onPortraitRollRightClick(
- characterSheetId: String,
- ) {
- rolls[characterSheetId]?.value = null
- }
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonRoll.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonRoll.kt
index b049735..259939f 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonRoll.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/campaign/player/ribbon/common/CharacterRibbonRoll.kt
@@ -5,8 +5,10 @@ import androidx.compose.animation.SizeTransform
import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Animatable
import androidx.compose.animation.core.AnimationVector1D
+import androidx.compose.animation.core.FastOutSlowInEasing
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
+import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
@@ -40,16 +42,29 @@ import org.jetbrains.compose.resources.painterResource
@Stable
data class CharacterRibbonRollUio(
+ val rollId: String,
+ val hideDelay: Int,
val characterSheetId: String,
val value: Int?,
val tint: Color?,
)
@Stable
-data class CharacterRibbonRollAnimation(
- val rotation: Animatable = Animatable(0f),
- val scale: Animatable = Animatable(1f),
-)
+class CharacterRibbonRollAnimation(
+ val animatedAlpha: Animatable,
+ val animatedRotation: Animatable,
+ val animatedScale: Animatable,
+) {
+ constructor(
+ alpha: Float = 1f,
+ rotation: Float = 0f,
+ scale: Float = 1f,
+ ) : this(
+ animatedAlpha = Animatable(alpha),
+ animatedRotation = Animatable(rotation),
+ animatedScale = Animatable(scale),
+ )
+}
@Composable
fun CharacterRibbonRoll(
@@ -69,13 +84,17 @@ fun CharacterRibbonRoll(
enter togetherWith exit using SizeTransform(clip = false)
}
) {
- val animation = diceIconAnimation(key = it ?: Unit)
+ val animation = diceIconAnimation(
+ key = it?.rollId ?: Unit,
+ rollDelay = it?.hideDelay ?: 1000,
+ )
val color = animateColorAsState(targetValue = it?.tint ?: Color.Transparent)
Box(
modifier = Modifier.graphicsLayer {
- this.scaleX = animation.scale.value
- this.scaleY = animation.scale.value
+ this.alpha = animation.animatedAlpha.value
+ this.scaleX = animation.animatedScale.value
+ this.scaleY = animation.animatedScale.value
},
contentAlignment = Alignment.Center,
) {
@@ -83,7 +102,7 @@ fun CharacterRibbonRoll(
Icon(
modifier = Modifier
.graphicsLayer {
- this.rotationZ = animation.rotation.value
+ this.rotationZ = animation.animatedRotation.value
}
.fillMaxWidth()
.aspectRatio(1f)
@@ -111,20 +130,23 @@ fun CharacterRibbonRoll(
}
@Composable
-private fun diceIconAnimation(key: Any = Unit): CharacterRibbonRollAnimation {
+private fun diceIconAnimation(
+ key: Any = Unit,
+ rollDelay: Int,
+): CharacterRibbonRollAnimation {
val animation = remember(key) {
CharacterRibbonRollAnimation()
}
LaunchedEffect(key) {
launch {
- animation.scale.animateTo(
+ animation.animatedScale.animateTo(
targetValue = 1.20f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
stiffness = 800f,
)
)
- animation.scale.animateTo(
+ animation.animatedScale.animateTo(
targetValue = 1f,
animationSpec = spring(
dampingRatio = 0.28f,
@@ -133,7 +155,7 @@ private fun diceIconAnimation(key: Any = Unit): CharacterRibbonRollAnimation {
)
}
launch {
- animation.rotation.animateTo(
+ animation.animatedRotation.animateTo(
targetValue = 360f * 3,
animationSpec = spring(
dampingRatio = Spring.DampingRatioNoBouncy,
@@ -141,6 +163,16 @@ private fun diceIconAnimation(key: Any = Unit): CharacterRibbonRollAnimation {
)
)
}
+ launch {
+ animation.animatedAlpha.animateTo(
+ targetValue = 0f,
+ animationSpec = tween(
+ delayMillis = rollDelay,
+ durationMillis = 2000,
+ easing = FastOutSlowInEasing,
+ )
+ )
+ }
}
return animation
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt
index b3ff792..771a2d6 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsScreen.kt
@@ -18,6 +18,7 @@ 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.runtime.Stable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
@@ -42,8 +43,11 @@ import lwacharactersheet.composeapp.generated.resources.settings__title
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel
+@Stable
object SettingsScreenDefault {
+ @Stable
val margin: PaddingValues = PaddingValues(horizontal = 16.dp)
+ @Stable
val padding: PaddingValues = PaddingValues(start = 16.dp, top = 8.dp, end = 8.dp, bottom = 8.dp)
}
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
index bc72c57..6560bb1 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/SettingsViewModel.kt
@@ -25,12 +25,14 @@ import lwacharactersheet.composeapp.generated.resources.settings__chat_log__auto
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__line_count_description
+import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_title
import lwacharactersheet.composeapp.generated.resources.settings__chat_log__section
+import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_delay_description
+import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_delay_tile
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_description
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__dyn_dice_tile
import lwacharactersheet.composeapp.generated.resources.settings__player_portrait__section
-import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_title
-import lwacharactersheet.composeapp.generated.resources.settings__chat_log__line_count_description
class SettingsViewModel(
@@ -58,6 +60,35 @@ class SettingsViewModel(
)
},
),
+ SettingNumberItemUio(
+ icon = Res.drawable.ic_timer_24dp,
+ title = Res.string.settings__player_portrait__dyn_dice_delay_tile,
+ description = Res.string.settings__player_portrait__dyn_dice_delay_description,
+ enable = booleanStates.dynamicDice,
+ value = intStates.dynamicDiceDelay,
+ onValueChange = {
+ val range = 1000..99999
+ if (it < range.first) {
+ settingsRepository.update(
+ settings = settings.value.copy(
+ portrait = settings.value.portrait.copy(dynamicDiceDelay = range.first)
+ )
+ )
+ } else if (it in range) {
+ settingsRepository.update(
+ settings = settings.value.copy(
+ portrait = settings.value.portrait.copy(dynamicDiceDelay = it)
+ )
+ )
+ } else {
+ settingsRepository.update(
+ settings = settings.value.copy(
+ portrait = settings.value.portrait.copy(dynamicDiceDelay = range.last)
+ )
+ )
+ }
+ }
+ ),
SettingSectionUio(
title = Res.string.settings__chat_log__section,
),
@@ -138,6 +169,7 @@ class SettingsViewModel(
viewModelScope.launch {
settingsRepository.settingsFlow().collect { settings ->
booleanStates.dynamicDice.value = settings.portrait.dynamicDice
+ intStates.dynamicDiceDelay.value = settings.portrait.dynamicDiceDelay
booleanStates.autoShowChat.value = settings.chat.autoShowChat
booleanStates.autoHideChat.value = settings.chat.autoHideChat
intStates.autoHideDelay.value = settings.chat.autoHideDelay
@@ -162,6 +194,9 @@ class SettingsViewModel(
private val HashMap>.dynamicDice
get() = getOrPut("DYNAMIC_DICE") { mutableStateOf(settings.value.portrait.dynamicDice) }
+ private val HashMap>.dynamicDiceDelay
+ get() = getOrPut("DYNAMIC_DICE_DELAY") { mutableStateOf(settings.value.portrait.dynamicDiceDelay) }
+
private val HashMap>.autoShowChat
get() = getOrPut("AUTO_SHOW_CHAT") { mutableStateOf(settings.value.chat.autoShowChat) }
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/composable/SettingNumberItem.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/composable/SettingNumberItem.kt
index dbbd591..79f3617 100644
--- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/composable/SettingNumberItem.kt
+++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/ui/screen/settings/composable/SettingNumberItem.kt
@@ -114,7 +114,7 @@ fun SettingNumberItem(
BasicTextField(
modifier = Modifier
.onFocusChanged { focused.value = it.isFocused }
- .width(width = 44.dp)
+ .width(width = 64.dp)
.padding(horizontal = 2.dp),
textStyle = MaterialTheme.lwa.typography.settings.input.copy(
color = textColor.value,
@@ -129,10 +129,9 @@ fun SettingNumberItem(
Box(
modifier = Modifier
.background(color = borderColor.value)
- .size(width = 48.dp, height = 2.dp),
+ .size(width = 64.dp, height = 2.dp),
)
}
}
}
-
}
\ No newline at end of file
diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/usecase/SettingsUseCase.kt
index c1f1d63..357b6ab 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
@@ -7,7 +7,8 @@ class SettingsUseCase {
fun defaultSettings(): Settings = Settings(
playerName = "",
portrait = Settings.Portrait(
- dynamicDice = true
+ dynamicDice = true,
+ dynamicDiceDelay = 5000,
),
chat = Settings.Chat(
autoHideChat = true,