Add roll values to the new UI
This commit is contained in:
parent
6385d4c8bd
commit
3c8eecdab5
16 changed files with 262 additions and 53 deletions
|
|
@ -8,3 +8,6 @@
|
||||||
|
|
||||||
# Kotlinx coroutines rules seems to be outdated with the latest version of Kotlin and Proguard
|
# Kotlinx coroutines rules seems to be outdated with the latest version of Kotlin and Proguard
|
||||||
-keep class kotlinx.coroutines.** { *; }
|
-keep class kotlinx.coroutines.** { *; }
|
||||||
|
|
||||||
|
# OkHttp comming from COIL.
|
||||||
|
-dontwarn okhttp3.internal.platform.**
|
||||||
|
|
@ -41,6 +41,7 @@ import com.pixelized.desktop.lwa.ui.navigation.window.destination.RollHistoryWin
|
||||||
import com.pixelized.desktop.lwa.ui.navigation.window.rememberMaxWindowHeight
|
import com.pixelized.desktop.lwa.ui.navigation.window.rememberMaxWindowHeight
|
||||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository.Status
|
import com.pixelized.desktop.lwa.repository.network.NetworkRepository.Status
|
||||||
|
import com.pixelized.desktop.lwa.ui.navigation.screen.MainNavHost
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CampaignScreen
|
import com.pixelized.desktop.lwa.ui.screen.campaign.player.CampaignScreen
|
||||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.CharacterSheetMainNavHost
|
import com.pixelized.desktop.lwa.ui.screen.characterSheet.CharacterSheetMainNavHost
|
||||||
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage
|
import com.pixelized.desktop.lwa.ui.screen.rollhistory.RollHistoryPage
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import com.pixelized.desktop.lwa.utils.extention.decodeFromFrame
|
||||||
import com.pixelized.desktop.lwa.utils.extention.encodeToFrame
|
import com.pixelized.desktop.lwa.utils.extention.encodeToFrame
|
||||||
import com.pixelized.server.lwa.SERVER_PORT
|
import com.pixelized.server.lwa.SERVER_PORT
|
||||||
import com.pixelized.server.lwa.protocol.Message
|
import com.pixelized.server.lwa.protocol.Message
|
||||||
import com.pixelized.server.lwa.protocol.MessageContent
|
import com.pixelized.server.lwa.protocol.MessageType
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.HttpClient
|
||||||
import io.ktor.websocket.Frame
|
import io.ktor.websocket.Frame
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -99,11 +99,13 @@ class NetworkRepository(
|
||||||
|
|
||||||
suspend fun share(
|
suspend fun share(
|
||||||
playerName: String = settingsRepository.settings().playerName,
|
playerName: String = settingsRepository.settings().playerName,
|
||||||
content: MessageContent,
|
type: MessageType,
|
||||||
|
content: String,
|
||||||
) {
|
) {
|
||||||
if (status.value == Status.CONNECTED) {
|
if (status.value == Status.CONNECTED) {
|
||||||
val message = Message(
|
val message = Message(
|
||||||
from = playerName,
|
from = playerName,
|
||||||
|
type = type,
|
||||||
value = content,
|
value = content,
|
||||||
)
|
)
|
||||||
// emit the message into the outgoing buffer
|
// emit the message into the outgoing buffer
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,28 @@
|
||||||
package com.pixelized.desktop.lwa.repository.roll_history
|
package com.pixelized.desktop.lwa.repository.roll_history
|
||||||
|
|
||||||
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
import com.pixelized.desktop.lwa.repository.network.NetworkRepository
|
||||||
import com.pixelized.server.lwa.protocol.Message
|
import com.pixelized.server.lwa.protocol.MessageType
|
||||||
import com.pixelized.server.lwa.protocol.RollMessage
|
import com.pixelized.server.lwa.protocol.roll.RollMessage
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.mapNotNull
|
import kotlinx.coroutines.flow.mapNotNull
|
||||||
import kotlinx.coroutines.flow.shareIn
|
import kotlinx.coroutines.flow.shareIn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
class RollHistoryRepository(
|
class RollHistoryRepository(
|
||||||
private val network: NetworkRepository,
|
private val network: NetworkRepository,
|
||||||
|
private val jsonFormatter: Json,
|
||||||
) {
|
) {
|
||||||
private val scope = CoroutineScope(Dispatchers.IO)
|
private val scope = CoroutineScope(Dispatchers.IO)
|
||||||
|
|
||||||
val rolls: SharedFlow<Message> = network.data
|
val rolls: SharedFlow<RollMessage> = network.data
|
||||||
.mapNotNull { it.takeIf { it.value is RollMessage } }
|
.mapNotNull { it.takeIf { it.type == MessageType.Roll } }
|
||||||
|
.map { jsonFormatter.decodeFromString<RollMessage>(it.value) }
|
||||||
.shareIn(
|
.shareIn(
|
||||||
scope = scope,
|
scope = scope,
|
||||||
started = SharingStarted.Eagerly,
|
started = SharingStarted.Eagerly,
|
||||||
|
|
@ -32,20 +37,24 @@ class RollHistoryRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun share(
|
suspend fun share(
|
||||||
|
characterId: String,
|
||||||
skillLabel: String,
|
skillLabel: String,
|
||||||
rollDifficulty: String?,
|
rollDifficulty: String?,
|
||||||
rollValue: Int,
|
rollValue: Int,
|
||||||
resultLabel: String?,
|
resultLabel: String?,
|
||||||
rollSuccessLimit: Int?,
|
rollSuccessLimit: Int?,
|
||||||
) {
|
) {
|
||||||
network.share(
|
val content = RollMessage(
|
||||||
content = RollMessage(
|
characterId = characterId,
|
||||||
skillLabel = skillLabel,
|
skillLabel = skillLabel,
|
||||||
rollDifficulty = rollDifficulty,
|
rollDifficulty = rollDifficulty,
|
||||||
rollValue = rollValue,
|
rollValue = rollValue,
|
||||||
resultLabel = resultLabel,
|
resultLabel = resultLabel,
|
||||||
rollSuccessLimit = rollSuccessLimit,
|
rollSuccessLimit = rollSuccessLimit,
|
||||||
)
|
)
|
||||||
|
network.share(
|
||||||
|
type = MessageType.Roll,
|
||||||
|
content = jsonFormatter.encodeToString(content),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,6 +9,7 @@ import androidx.compose.foundation.layout.height
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.material.Surface
|
import androidx.compose.material.Surface
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
|
@ -30,13 +31,19 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetai
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel
|
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDiminishedViewModel
|
||||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbon
|
import com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon.PlayerRibbon
|
||||||
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialog
|
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.dialog.DiminishedStatDialog
|
||||||
|
import com.pixelized.desktop.lwa.ui.screen.network.NetworkViewModel
|
||||||
import org.koin.compose.viewmodel.koinViewModel
|
import org.koin.compose.viewmodel.koinViewModel
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CampaignScreen(
|
fun CampaignScreen(
|
||||||
characterDetailViewModel: CharacterDetailViewModel = koinViewModel(),
|
characterDetailViewModel: CharacterDetailViewModel = koinViewModel(),
|
||||||
dismissedViewModel: CharacterDiminishedViewModel = koinViewModel(),
|
dismissedViewModel: CharacterDiminishedViewModel = koinViewModel(),
|
||||||
|
networkViewModel: NetworkViewModel = koinViewModel(),
|
||||||
) {
|
) {
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
networkViewModel.connect()
|
||||||
|
}
|
||||||
|
|
||||||
KeyHandler {
|
KeyHandler {
|
||||||
when {
|
when {
|
||||||
it.type == KeyEventType.KeyUp && it.key == Key.Escape -> {
|
it.type == KeyEventType.KeyUp && it.key == Key.Escape -> {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,129 @@
|
||||||
|
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedContent
|
||||||
|
import androidx.compose.animation.SizeTransform
|
||||||
|
import androidx.compose.animation.core.Animatable
|
||||||
|
import androidx.compose.animation.core.AnimationVector1D
|
||||||
|
import androidx.compose.animation.core.Spring
|
||||||
|
import androidx.compose.animation.core.spring
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.togetherWith
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
|
import androidx.compose.ui.graphics.Shadow
|
||||||
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
|
import androidx.compose.ui.text.style.TextAlign
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.Res
|
||||||
|
import lwacharactersheet.composeapp.generated.resources.ic_d20_24dp
|
||||||
|
import org.jetbrains.compose.resources.painterResource
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
data class PlayerPortraitRollAnimation(
|
||||||
|
val alpha: Animatable<Float, AnimationVector1D> = Animatable(0f),
|
||||||
|
val rotation: Animatable<Float, AnimationVector1D> = Animatable(0f),
|
||||||
|
val scale: Animatable<Float, AnimationVector1D> = Animatable(1f),
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun PlayerPortraitRoll(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
value: Int?,
|
||||||
|
) {
|
||||||
|
AnimatedContent(
|
||||||
|
modifier = modifier.graphicsLayer { clip = false },
|
||||||
|
targetState = value,
|
||||||
|
transitionSpec = {
|
||||||
|
val enter = fadeIn()
|
||||||
|
val exit = fadeOut()
|
||||||
|
enter togetherWith exit using SizeTransform(clip = false)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
val animation = diceIconAnimation(key = it ?: Unit)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.graphicsLayer {
|
||||||
|
this.scaleX = animation.scale.value
|
||||||
|
this.scaleY = animation.scale.value
|
||||||
|
},
|
||||||
|
contentAlignment = Alignment.Center,
|
||||||
|
) {
|
||||||
|
when (it) {
|
||||||
|
null -> Unit
|
||||||
|
else -> {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier
|
||||||
|
.graphicsLayer {
|
||||||
|
this.alpha = 0.8f
|
||||||
|
this.rotationZ = animation.rotation.value
|
||||||
|
}
|
||||||
|
.size(48.dp),
|
||||||
|
painter = painterResource(Res.drawable.ic_d20_24dp),
|
||||||
|
tint = MaterialTheme.colors.primary,
|
||||||
|
contentDescription = null,
|
||||||
|
)
|
||||||
|
Text(
|
||||||
|
style = MaterialTheme.typography.h5.copy(
|
||||||
|
shadow = Shadow(
|
||||||
|
color = MaterialTheme.colors.surface,
|
||||||
|
offset = Offset.Zero,
|
||||||
|
blurRadius = 8f,
|
||||||
|
)
|
||||||
|
),
|
||||||
|
textAlign = TextAlign.Center,
|
||||||
|
color = MaterialTheme.colors.onSurface,
|
||||||
|
text = it.toString()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun diceIconAnimation(key: Any = Unit): PlayerPortraitRollAnimation {
|
||||||
|
val animation = remember(key) {
|
||||||
|
PlayerPortraitRollAnimation()
|
||||||
|
}
|
||||||
|
LaunchedEffect(key) {
|
||||||
|
launch {
|
||||||
|
animation.scale.animateTo(
|
||||||
|
targetValue = 1.20f,
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = Spring.DampingRatioNoBouncy,
|
||||||
|
stiffness = 800f,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
animation.scale.animateTo(
|
||||||
|
targetValue = 1f,
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = 0.28f,
|
||||||
|
stiffness = 800f,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
launch {
|
||||||
|
animation.rotation.animateTo(
|
||||||
|
targetValue = 360f * 3,
|
||||||
|
animationSpec = spring(
|
||||||
|
dampingRatio = Spring.DampingRatioNoBouncy,
|
||||||
|
stiffness = Spring.StiffnessLow,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return animation
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,8 @@
|
||||||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
||||||
|
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
import androidx.compose.foundation.lazy.items
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
|
|
@ -25,10 +27,19 @@ fun PlayerRibbon(
|
||||||
items = characters.value,
|
items = characters.value,
|
||||||
key = { it.id },
|
key = { it.id },
|
||||||
) {
|
) {
|
||||||
|
Row {
|
||||||
PlayerPortrait(
|
PlayerPortrait(
|
||||||
character = it,
|
character = it,
|
||||||
onCharacter = onCharacter,
|
onCharacter = onCharacter,
|
||||||
)
|
)
|
||||||
|
PlayerPortraitRoll(
|
||||||
|
modifier = Modifier.size(
|
||||||
|
width = 64.dp,
|
||||||
|
height = PlayerPortrait.Default.size.height
|
||||||
|
),
|
||||||
|
value = playerRibbonViewModel.roll(characterId = it.id).value,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,17 +1,26 @@
|
||||||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
package com.pixelized.desktop.lwa.ui.screen.campaign.player.ribbon
|
||||||
|
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||||
|
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.stateIn
|
import kotlinx.coroutines.flow.stateIn
|
||||||
|
|
||||||
class PlayerRibbonViewModel(
|
class PlayerRibbonViewModel(
|
||||||
repository: CharacterSheetRepository,
|
private val rollHistoryRepository: RollHistoryRepository,
|
||||||
|
characterRepository: CharacterSheetRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
val characters: StateFlow<List<PlayerPortraitUio>> = characterRepository.characterSheetFlow()
|
||||||
val characters = repository.characterSheetFlow()
|
|
||||||
.map { sheets ->
|
.map { sheets ->
|
||||||
sheets.map { sheet ->
|
sheets.map { sheet ->
|
||||||
PlayerPortraitUio(
|
PlayerPortraitUio(
|
||||||
|
|
@ -28,4 +37,31 @@ class PlayerRibbonViewModel(
|
||||||
started = SharingStarted.Eagerly,
|
started = SharingStarted.Eagerly,
|
||||||
initialValue = emptyList()
|
initialValue = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private val _rolls: HashMap<String, Int?> = hashMapOf()
|
||||||
|
val rolls: StateFlow<Map<String, Int?>> = rollHistoryRepository.rolls
|
||||||
|
.map {
|
||||||
|
_rolls[it.characterId] = it.rollValue
|
||||||
|
_rolls
|
||||||
|
}.stateIn(
|
||||||
|
scope = viewModelScope,
|
||||||
|
started = SharingStarted.Eagerly,
|
||||||
|
initialValue = emptyMap()
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Stable
|
||||||
|
fun roll(characterId: String): State<Int?> {
|
||||||
|
val state = rememberSaveable(characterId) {
|
||||||
|
mutableStateOf<Int?>(null)
|
||||||
|
}
|
||||||
|
LaunchedEffect(characterId) {
|
||||||
|
rollHistoryRepository.rolls.collect {
|
||||||
|
if (it.characterId == characterId) {
|
||||||
|
state.value = it.rollValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return state
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -95,13 +95,16 @@ fun RollPage(
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
KeyHandler {
|
KeyHandler {
|
||||||
if (it.type == KeyEventType.KeyUp && it.key == Key.Escape) {
|
when {
|
||||||
|
it.type == KeyEventType.KeyUp && it.key == Key.Escape -> {
|
||||||
onDismissRequest()
|
onDismissRequest()
|
||||||
true
|
true
|
||||||
} else {
|
}
|
||||||
|
else -> {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
|
|
|
||||||
|
|
@ -192,6 +192,7 @@ class RollViewModel(
|
||||||
)
|
)
|
||||||
launch {
|
launch {
|
||||||
rollHistoryRepository.share(
|
rollHistoryRepository.share(
|
||||||
|
characterId = sheet.id,
|
||||||
skillLabel = _rollTitle.value.label,
|
skillLabel = _rollTitle.value.label,
|
||||||
rollDifficulty = when (_rollDifficulty.value?.difficulty) {
|
rollDifficulty = when (_rollDifficulty.value?.difficulty) {
|
||||||
Difficulty.EASY -> getString(Res.string.roll_page__dc_easy__label)
|
Difficulty.EASY -> getString(Res.string.roll_page__dc_easy__label)
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import org.jetbrains.compose.resources.stringResource
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
data class RollHistoryItemUio(
|
data class RollHistoryItemUio(
|
||||||
val from: String,
|
val character: String,
|
||||||
val skillLabel: String,
|
val skillLabel: String,
|
||||||
val rollDifficulty: String?,
|
val rollDifficulty: String?,
|
||||||
val rollValue: Int,
|
val rollValue: Int,
|
||||||
|
|
@ -50,7 +50,7 @@ fun RollHistoryItem(
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
text = roll.from,
|
text = roll.character,
|
||||||
)
|
)
|
||||||
Text(
|
Text(
|
||||||
modifier = Modifier.alignByBaseline(),
|
modifier = Modifier.alignByBaseline(),
|
||||||
|
|
|
||||||
|
|
@ -4,12 +4,15 @@ import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.pixelized.server.lwa.protocol.RollMessage
|
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
|
||||||
|
import com.pixelized.desktop.lwa.repository.characterSheet.model.CharacterSheet
|
||||||
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
import com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class RollHistoryViewModel(
|
class RollHistoryViewModel(
|
||||||
private val repository: RollHistoryRepository
|
private val characterRepository: CharacterSheetRepository,
|
||||||
|
private val rollRepository: RollHistoryRepository,
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
|
||||||
private val _rolls = mutableStateOf((emptyList<RollHistoryItemUio>()))
|
private val _rolls = mutableStateOf((emptyList<RollHistoryItemUio>()))
|
||||||
|
|
@ -17,13 +20,15 @@ class RollHistoryViewModel(
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
repository.rolls.collect {
|
combine(
|
||||||
(it.value as? RollMessage)?.let { content ->
|
characterRepository.characterSheetFlow(),
|
||||||
_rolls.value = _rolls.value.toMutableList().apply {
|
rollRepository.rolls,
|
||||||
|
) { sheets: List<CharacterSheet>, content ->
|
||||||
|
_rolls.value.toMutableList().apply {
|
||||||
add(
|
add(
|
||||||
index = 0,
|
index = 0,
|
||||||
element = RollHistoryItemUio(
|
element = RollHistoryItemUio(
|
||||||
from = it.from,
|
character = sheets.firstOrNull { it.id == content.characterId }?.name ?: "",
|
||||||
skillLabel = content.skillLabel,
|
skillLabel = content.skillLabel,
|
||||||
rollDifficulty = content.rollDifficulty,
|
rollDifficulty = content.rollDifficulty,
|
||||||
resultLabel = content.resultLabel,
|
resultLabel = content.resultLabel,
|
||||||
|
|
@ -32,7 +37,8 @@ class RollHistoryViewModel(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}.collect { content ->
|
||||||
|
_rolls.value = content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,6 @@ import kotlinx.serialization.Serializable
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Message(
|
data class Message(
|
||||||
val from: String,
|
val from: String,
|
||||||
val value: MessageContent,
|
val type: MessageType,
|
||||||
|
val value: String,
|
||||||
)
|
)
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package com.pixelized.server.lwa.protocol
|
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
|
|
||||||
@Serializable
|
|
||||||
sealed interface MessageContent
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.pixelized.server.lwa.protocol
|
||||||
|
|
||||||
|
enum class MessageType {
|
||||||
|
Roll
|
||||||
|
}
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
package com.pixelized.server.lwa.protocol
|
package com.pixelized.server.lwa.protocol.roll
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class RollMessage(
|
data class RollMessage(
|
||||||
|
val characterId: String,
|
||||||
val skillLabel: String,
|
val skillLabel: String,
|
||||||
val resultLabel: String?,
|
val resultLabel: String?,
|
||||||
val rollDifficulty: String?,
|
val rollDifficulty: String?,
|
||||||
val rollValue: Int,
|
val rollValue: Int,
|
||||||
val rollSuccessLimit: Int?,
|
val rollSuccessLimit: Int?,
|
||||||
) : MessageContent
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue