Add characteristic to the campagin detail panel.

This commit is contained in:
Thomas Andres Gomez 2025-02-26 17:13:47 +01:00
parent 29747dcb5c
commit b6b135cd40
12 changed files with 690 additions and 331 deletions

View file

@ -9,6 +9,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
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.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.BlurredEdgeTreatment import androidx.compose.ui.draw.BlurredEdgeTreatment
import androidx.compose.ui.draw.blur import androidx.compose.ui.draw.blur
@ -36,6 +37,20 @@ class BlurContentController(
} }
} }
@Composable
@Stable
fun rememberBlurContentController(
blurred: Boolean = false,
blurredRadius: Dp = 8.dp,
scrimColor: Color = LwaColorPalette.DefaultScrimColor,
) = remember {
BlurContentController(
blurred = blurred,
blurredRadius = blurredRadius,
scrimColor = scrimColor,
)
}
@Composable @Composable
fun BlurContent( fun BlurContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,

View file

@ -33,9 +33,11 @@ class CharacterDetailCharacteristicDialogViewModel(
} }
suspend fun showSubCharacteristicDialog( suspend fun showSubCharacteristicDialog(
characterInstanceId: Campaign.CharacterInstance.Id, characterInstanceId: Campaign.CharacterInstance.Id?,
characteristic: Characteristic, characteristic: Characteristic,
) { ) {
if (characterInstanceId == null) return
val sheet: CharacterSheet? = characterSheetRepository.characterDetail( val sheet: CharacterSheet? = characterSheetRepository.characterDetail(
characterSheetId = characterInstanceId.characterSheetId, characterSheetId = characterInstanceId.characterSheetId,
) )

View file

@ -1,5 +1,11 @@
package com.pixelized.desktop.lwa.ui.screen.campaign package com.pixelized.desktop.lwa.ui.screen.campaign
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith
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.fillMaxHeight import androidx.compose.foundation.layout.fillMaxHeight
@ -7,12 +13,14 @@ import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
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.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
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.input.key.Key import androidx.compose.ui.input.key.Key
@ -25,20 +33,29 @@ import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.blur.BlurContent
import com.pixelized.desktop.lwa.ui.composable.blur.rememberBlurContentController
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog
import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetail import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailViewModel
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 com.pixelized.desktop.lwa.ui.screen.network.NetworkViewModel
import com.pixelized.desktop.lwa.ui.screen.roll.RollPage
import com.pixelized.desktop.lwa.ui.screen.roll.RollViewModel
import kotlinx.coroutines.launch
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
@Composable @Composable
fun CampaignScreen( fun CampaignScreen(
characterDetailViewModel: CharacterDetailViewModel = koinViewModel(), characterDetailViewModel: CharacterDetailViewModel = koinViewModel(),
characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel = koinViewModel(),
dismissedViewModel: CharacterDiminishedViewModel = koinViewModel(), dismissedViewModel: CharacterDiminishedViewModel = koinViewModel(),
networkViewModel: NetworkViewModel = koinViewModel(), networkViewModel: NetworkViewModel = koinViewModel(),
rollViewModel: RollViewModel = koinViewModel(),
) { ) {
LaunchedEffect(Unit) { LaunchedEffect(Unit) {
networkViewModel.connect() networkViewModel.connect()
@ -55,48 +72,105 @@ fun CampaignScreen(
} }
} }
Surface { val scope = rememberCoroutineScope()
CampaignScreenLayout( val blurController = rememberBlurContentController()
Surface(
modifier = Modifier.fillMaxSize(),
) {
BlurContent(
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize(),
top = { controller = blurController
Surface( ) {
modifier = Modifier CampaignScreenLayout(
.height(32.dp) modifier = Modifier.fillMaxSize(),
.fillMaxWidth(), top = {
elevation = 1.dp, Surface(
) { modifier = Modifier
.height(32.dp)
.fillMaxWidth(),
elevation = 1.dp,
) {
} }
}, },
bottom = { bottom = {
Surface( Surface(
modifier = Modifier modifier = Modifier
.height(48.dp) .height(48.dp)
.fillMaxWidth(), .fillMaxWidth(),
elevation = 1.dp, elevation = 1.dp,
) { ) {
} }
}, },
main = { main = {
},
leftOverlay = {
PlayerRibbon(
modifier = Modifier.fillMaxHeight(),
onCharacter = {
characterDetailViewModel.showCharacter(id = it)
},
)
},
rightOverlay = {
CharacterDetailPanel(
modifier = Modifier
.width(width = 128.dp * 4)
.fillMaxHeight()
.padding(all = 8.dp),
blurController = blurController,
detailViewModel = characterDetailViewModel,
rollViewModel = rollViewModel,
characterDiminishedViewModel = dismissedViewModel,
characteristicDialogViewModel = characteristicDialogViewModel,
)
},
)
}
AnimatedContent(
modifier = Modifier.fillMaxSize(),
targetState = rollViewModel.displayOverlay.value,
transitionSpec = {
val enter = fadeIn() + slideInVertically { 64 }
val exit = fadeOut() + slideOutVertically { 64 }
enter togetherWith exit
}, },
leftOverlay = { ) { roll ->
PlayerRibbon( when (roll) {
modifier = Modifier.fillMaxHeight(), true -> RollPage(
onCharacter = { viewModel = rollViewModel,
characterDetailViewModel.showCharacter(id = it) onDismissRequest = {
blurController.hide()
rollViewModel.hideOverlay()
}, },
) )
},
rightOverlay = { else -> Box(
CharacterDetail( modifier = Modifier.fillMaxSize()
modifier = Modifier
.padding(all = 8.dp)
.fillMaxHeight(),
detailViewModel = characterDetailViewModel,
dismissedViewModel = dismissedViewModel,
) )
}
}
CharacterSheetCharacteristicDialog(
dialog = characteristicDialogViewModel.statChangeDialog,
onConfirm = { dialog ->
scope.launch {
characteristicDialogViewModel.changeSubCharacteristic(
characterInstanceId = dialog.characterInstanceId,
characteristic = dialog.characteristic,
value = dialog.value().text.toIntOrNull() ?: 0,
)
characteristicDialogViewModel.hideSubCharacteristicDialog()
blurController.hide()
}
},
onDismissRequest = {
characteristicDialogViewModel.hideSubCharacteristicDialog()
blurController.hide()
}, },
) )

View file

@ -6,141 +6,150 @@ import androidx.compose.animation.ExitTransition
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.animation.slideInHorizontally import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.clickable
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.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
import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.layout.width import androidx.compose.foundation.verticalScroll
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.MaterialTheme
import androidx.compose.material.Surface import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
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.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController import com.pixelized.desktop.lwa.ui.composable.blur.BlurContentController
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterDetailCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeader
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheet
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetCharacteristicUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetUio
import com.pixelized.desktop.lwa.ui.screen.roll.RollViewModel
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_close_24dp
import lwacharactersheet.composeapp.generated.resources.ic_heart_24dp
import lwacharactersheet.composeapp.generated.resources.ic_near_me
import lwacharactersheet.composeapp.generated.resources.ic_skull_24dp
import lwacharactersheet.composeapp.generated.resources.ic_water_drop_24dp
import org.jetbrains.compose.resources.painterResource
import org.koin.compose.viewmodel.koinViewModel
@Stable @Stable
data class CharacterDetailHeaderUio( data class CharacterDetailPanelUio(
val id: Campaign.CharacterInstance.Id, val characterInstanceId: Campaign.CharacterInstance.Id?,
val portrait: String?, val header: StateFlow<CharacterDetailHeaderUio?>,
val name: String, val sheet: StateFlow<CharacterDetailSheetUio?>,
val hp: String,
val maxHp: String,
val pp: String,
val maxPp: String,
val mov: String,
) )
@Composable @Composable
fun CharacterDetail( fun CharacterDetailPanel(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
dismissedViewModel: CharacterDiminishedViewModel, blurController: BlurContentController,
detailViewModel: CharacterDetailViewModel = koinViewModel(), detailViewModel: CharacterDetailViewModel,
characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel = koinViewModel(), characteristicDialogViewModel: CharacterDetailCharacteristicDialogViewModel,
characterDiminishedViewModel: CharacterDiminishedViewModel,
rollViewModel: RollViewModel,
) { ) {
val blurController = remember { BlurContentController() }
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val detail = detailViewModel.detail.collectAsState() val detail: State<CharacterDetailPanelUio> = detailViewModel.detail.collectAsState()
AnimatedContent( CharacterDetailAnimatedPanel(
modifier = modifier, modifier = modifier,
targetState = detail.value, detail = detail,
transitionSpec = { onDismissRequest = {
if (initialState?.id != targetState?.id) { detailViewModel.hideCharacter()
(fadeIn() + slideInHorizontally { it / 2 }).togetherWith(fadeOut()) },
} else { onDiminished = {
EnterTransition.None togetherWith ExitTransition.None scope.launch {
characterDiminishedViewModel.showDiminishedDialog(
characterInstanceId = it
)
} }
} },
) { onHp = {
when (it) { scope.launch {
null -> Box( blurController.show()
modifier = Modifier.fillMaxHeight(), characteristicDialogViewModel.showSubCharacteristicDialog(
characterInstanceId = it,
characteristic = Campaign.CharacterInstance.Characteristic.Damage,
)
}
},
onPp = {
scope.launch {
blurController.show()
characteristicDialogViewModel.showSubCharacteristicDialog(
characterInstanceId = it,
characteristic = Campaign.CharacterInstance.Characteristic.Power,
)
}
},
onCharacteristic = {
rollViewModel.prepareRoll(
characterSheetId = detail.value.characterInstanceId?.characterSheetId!!,
label = it.label,
rollAction = "1d100",
rollSuccessValue = (it.value.toIntOrNull() ?: 0) * 5,
) )
blurController.show()
rollViewModel.showOverlay()
},
)
}
else -> { @Composable
Box( fun CharacterDetailAnimatedPanel(
modifier = Modifier modifier: Modifier = Modifier,
.fillMaxHeight() detail: State<CharacterDetailPanelUio>,
.width(width = 128.dp * 4), onDismissRequest: (id: Campaign.CharacterInstance.Id) -> Unit,
) { onDiminished: (id: Campaign.CharacterInstance.Id) -> Unit,
CharacterDetailContent( onHp: (id: Campaign.CharacterInstance.Id) -> Unit,
onPp: (id: Campaign.CharacterInstance.Id) -> Unit,
onCharacteristic: (CharacterDetailSheetCharacteristicUio) -> Unit,
) {
Box(
modifier = modifier,
) {
AnimatedContent(
modifier = Modifier.matchParentSize(),
targetState = detail.value,
transitionSpec = {
if (initialState.characterInstanceId != targetState.characterInstanceId) {
val enter = fadeIn() + slideInHorizontally { it / 2 }
val exit = fadeOut() + slideOutHorizontally { it / 2 }
enter togetherWith exit
} else {
EnterTransition.None togetherWith ExitTransition.None
}
}
) {
when {
it.characterInstanceId == null -> Box(
modifier = Modifier.matchParentSize(),
)
else -> {
Box(
modifier = Modifier.matchParentSize(), modifier = Modifier.matchParentSize(),
character = it, ) {
onDismissRequest = { CharacterDetailContent(
detailViewModel.hideCharacter() modifier = Modifier.matchParentSize(),
}, header = it.header.collectAsState(),
onDiminished = { sheet = it.sheet.collectAsState(),
scope.launch { onDismissRequest = { onDismissRequest(it.characterInstanceId) },
dismissedViewModel.showDiminishedDialog(id = it.id) onDiminished = { onDiminished(it.characterInstanceId) },
} onHp = { onHp(it.characterInstanceId) },
}, onPp = { onPp(it.characterInstanceId) },
onHp = { onCharacteristic = onCharacteristic,
scope.launch { )
characteristicDialogViewModel.showSubCharacteristicDialog( }
characterInstanceId = it.id,
characteristic = Campaign.CharacterInstance.Characteristic.Damage,
)
}
},
onPp = {
scope.launch {
characteristicDialogViewModel.showSubCharacteristicDialog(
characterInstanceId = it.id,
characteristic = Campaign.CharacterInstance.Characteristic.Power,
)
}
},
)
CharacterSheetCharacteristicDialog(
dialog = characteristicDialogViewModel.statChangeDialog,
onConfirm = { dialog ->
scope.launch {
characteristicDialogViewModel.changeSubCharacteristic(
characterInstanceId = dialog.characterInstanceId,
characteristic = dialog.characteristic,
value = dialog.value().text.toIntOrNull() ?: 0,
)
characteristicDialogViewModel.hideSubCharacteristicDialog()
blurController.hide()
}
},
onDismissRequest = {
characteristicDialogViewModel.hideSubCharacteristicDialog()
blurController.hide()
}
)
} }
} }
} }
@ -150,169 +159,35 @@ fun CharacterDetail(
@Composable @Composable
fun CharacterDetailContent( fun CharacterDetailContent(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
character: CharacterDetailHeaderUio, header: State<CharacterDetailHeaderUio?>,
sheet: State<CharacterDetailSheetUio?>,
onDismissRequest: () -> Unit, onDismissRequest: () -> Unit,
onDiminished: () -> Unit, onDiminished: () -> Unit,
onHp: () -> Unit, onHp: () -> Unit,
onPp: () -> Unit, onPp: () -> Unit,
) { onCharacteristic: (CharacterDetailSheetCharacteristicUio) -> Unit,
Box(
modifier = modifier,
) {
Background(
character = character,
)
Column {
CharacterHeader(
modifier = Modifier.padding(start = 16.dp).fillMaxWidth(),
character = character,
onDismissRequest = onDismissRequest,
onDiminished = onDiminished,
onHp = onHp,
onPp = onPp,
)
}
}
}
@Composable
private fun Background(
modifier: Modifier = Modifier,
character: CharacterDetailHeaderUio,
) { ) {
Surface( Surface(
modifier = modifier.fillMaxSize(), modifier = modifier.fillMaxSize(),
color = MaterialTheme.lwa.colorScheme.elevatedSurface, color = MaterialTheme.lwa.colorScheme.elevatedSurface,
) { ) {
// Image( Column {
// modifier = Modifier.fillMaxSize().drawWithContent { CharacterDetailHeader(
// drawContent() modifier = Modifier.padding(start = 16.dp).fillMaxWidth(),
// drawRect( header = header,
// brush = Brush.verticalGradient( onDismissRequest = onDismissRequest,
// listOfNotNull( onDiminished = onDiminished,
// color?.copy(alpha = 0.7f), onHp = onHp,
// color, onPp = onPp,
// ) )
// ) CharacterDetailSheet(
// ) modifier = Modifier
// }, .weight(1f)
// painter = rememberAsyncImagePainter(model = character.portrait), .verticalScroll(state = rememberScrollState())
// contentDescription = null, .padding(all = 16.dp),
// contentScale = ContentScale.Crop, sheet = sheet,
// alignment = Alignment.TopCenter, onCharacteristic = onCharacteristic,
// )
}
}
@Composable
private fun CharacterHeader(
modifier: Modifier = Modifier,
character: CharacterDetailHeaderUio,
onDismissRequest: () -> Unit,
onDiminished: () -> Unit,
onHp: () -> Unit,
onPp: () -> Unit,
) {
Column(
modifier = modifier,
) {
Row {
Text(
modifier = Modifier.weight(1f)
.align(alignment = Alignment.CenterVertically),
style = MaterialTheme.typography.h5,
text = character.name,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
) )
IconButton(
onClick = onDiminished,
) {
Icon(
modifier = Modifier.size(size = 24.dp),
painter = painterResource(Res.drawable.ic_skull_24dp),
tint = MaterialTheme.colors.primary,
contentDescription = null,
)
}
IconButton(
onClick = onDismissRequest,
) {
Icon(
painter = painterResource(Res.drawable.ic_close_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null,
)
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(space = 12.dp),
) {
Row(
modifier = Modifier.clip(shape = CircleShape).clickable { onHp() },
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_heart_24dp),
contentDescription = null
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
color = MaterialTheme.lwa.colorScheme.base.primary,
fontWeight = FontWeight.Bold,
text = character.hp,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Thin,
text = "/${character.maxHp}",
)
}
Row(
modifier = Modifier.clip(shape = CircleShape).clickable { onPp() },
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_water_drop_24dp),
contentDescription = null
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
color = MaterialTheme.lwa.colorScheme.base.primary,
fontWeight = FontWeight.Bold,
text = character.pp,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Thin,
text = "/${character.maxPp}",
)
}
Row(
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_near_me),
contentDescription = null,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
text = character.mov,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
text = "m",
)
}
} }
} }
} }

View file

@ -1,16 +1,35 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header.CharacterDetailHeaderUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetCharacteristicUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet.CharacterDetailSheetUio
import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory import com.pixelized.shared.lwa.model.AlteredCharacterSheetFactory
import com.pixelized.shared.lwa.model.alteration.FieldAlteration import com.pixelized.shared.lwa.model.alteration.FieldAlteration
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import com.pixelized.shared.lwa.model.campaign.damage import com.pixelized.shared.lwa.model.campaign.damage
import com.pixelized.shared.lwa.model.campaign.power import com.pixelized.shared.lwa.model.campaign.power
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__cha
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__con
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__dex
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__hei
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__int
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__pow
import lwacharactersheet.composeapp.generated.resources.character_sheet__characteristics__str
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__charisma
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__constitution
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__dexterity
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__height
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__intelligence
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__power
import lwacharactersheet.composeapp.generated.resources.tooltip__characteristics__strength
import org.jetbrains.compose.resources.getString
class CharacterDetailFactory( class CharacterDetailFactory(
private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory, private val alteredCharacterSheetFactory: AlteredCharacterSheetFactory,
) { ) {
fun convertToCharacterDetailHeaderUio( fun convertToCharacterDetailHeaderUio(
characterInstanceId: Campaign.CharacterInstance.Id, characterInstanceId: Campaign.CharacterInstance.Id,
characterSheet: CharacterSheet?, characterSheet: CharacterSheet?,
@ -38,4 +57,80 @@ class CharacterDetailFactory(
mov = "${alteredCharacterSheet.movement}" mov = "${alteredCharacterSheet.movement}"
) )
} }
suspend fun convertToCharacterDetailSheetUio(
characterInstanceId: Campaign.CharacterInstance.Id,
characterSheet: CharacterSheet?,
characterInstance: Campaign.CharacterInstance,
alterations: Map<String, List<FieldAlteration>>,
): CharacterDetailSheetUio? {
if (characterSheet == null) return null
val alteredCharacterSheet = alteredCharacterSheetFactory.sheet(
characterSheet = characterSheet,
alterations = alterations,
)
return CharacterDetailSheetUio(
characterInstanceId = characterInstanceId,
characteristics = listOf(
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__str),
value = "${alteredCharacterSheet.strength}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__str),
description = getString(Res.string.tooltip__characteristics__strength),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__dex),
value = "${alteredCharacterSheet.dexterity}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__dex),
description = getString(Res.string.tooltip__characteristics__dexterity),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__con),
value = "${alteredCharacterSheet.constitution}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__con),
description = getString(Res.string.tooltip__characteristics__constitution),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__hei),
value = "${alteredCharacterSheet.height}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__hei),
description = getString(Res.string.tooltip__characteristics__height),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__int),
value = "${alteredCharacterSheet.intelligence}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__int),
description = getString(Res.string.tooltip__characteristics__intelligence),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__pow),
value = "${alteredCharacterSheet.power}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__pow),
description = getString(Res.string.tooltip__characteristics__power),
),
),
CharacterDetailSheetCharacteristicUio(
label = getString(Res.string.character_sheet__characteristics__cha),
value = "${alteredCharacterSheet.charisma}",
tooltips = TooltipUio(
title = getString(Res.string.character_sheet__characteristics__cha),
description = getString(Res.string.tooltip__characteristics__charisma),
),
),
)
)
}
} }

View file

@ -6,13 +6,11 @@ import com.pixelized.desktop.lwa.repository.alteration.AlterationRepository
import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository import com.pixelized.desktop.lwa.repository.campaign.CampaignRepository
import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository import com.pixelized.desktop.lwa.repository.characterSheet.CharacterSheetRepository
import com.pixelized.shared.lwa.model.campaign.Campaign import com.pixelized.shared.lwa.model.campaign.Campaign
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.stateIn
class CharacterDetailViewModel( class CharacterDetailViewModel(
@ -24,32 +22,50 @@ class CharacterDetailViewModel(
private val displayedCharacterId = MutableStateFlow<Campaign.CharacterInstance.Id?>(null) private val displayedCharacterId = MutableStateFlow<Campaign.CharacterInstance.Id?>(null)
@OptIn(ExperimentalCoroutinesApi::class) val detail: StateFlow<CharacterDetailPanelUio> = displayedCharacterId
val detail: StateFlow<CharacterDetailHeaderUio?> = displayedCharacterId .map { characterInstanceId ->
.flatMapLatest { characterInstanceId -> if (characterInstanceId == null) return@map empty()
if (characterInstanceId != null) {
campaignRepository CharacterDetailPanelUio(
.characterInstanceFlow(id = characterInstanceId) characterInstanceId = characterInstanceId,
.flatMapLatest { characterInstance -> header = combine(
combine( campaignRepository.characterInstanceFlow(id = characterInstanceId),
characterSheetRepository.characterDetailFlow(characterId = characterInstanceId.characterSheetId), characterSheetRepository.characterDetailFlow(characterId = characterInstanceId.characterSheetId),
alterationRepository.alterationsFlow(characterId = characterInstanceId), alterationRepository.alterationsFlow(characterId = characterInstanceId),
) { characterSheet, alterations -> ) { characterInstance, characterSheet, alterations ->
characterDetailFactory.convertToCharacterDetailHeaderUio( characterDetailFactory.convertToCharacterDetailHeaderUio(
characterInstanceId = characterInstanceId, characterInstanceId = characterInstanceId,
characterSheet = characterSheet, characterSheet = characterSheet,
characterInstance = characterInstance, characterInstance = characterInstance,
alterations = alterations, alterations = alterations,
) )
} }.stateIn(
} scope = viewModelScope,
} else { started = SharingStarted.Eagerly,
flowOf(null) initialValue = null,
} ),
}.stateIn( sheet = combine(
campaignRepository.characterInstanceFlow(id = characterInstanceId),
characterSheetRepository.characterDetailFlow(characterId = characterInstanceId.characterSheetId),
alterationRepository.alterationsFlow(characterId = characterInstanceId),
) { characterInstance, characterSheet, alterations ->
characterDetailFactory.convertToCharacterDetailSheetUio(
characterInstanceId = characterInstanceId,
characterSheet = characterSheet,
characterInstance = characterInstance,
alterations = alterations,
)
}.stateIn(
scope = viewModelScope,
started = SharingStarted.Eagerly,
initialValue = null,
),
)
}
.stateIn(
scope = viewModelScope, scope = viewModelScope,
started = SharingStarted.Eagerly, started = SharingStarted.Eagerly,
initialValue = null, initialValue = empty(),
) )
fun showCharacter(id: Campaign.CharacterInstance.Id) { fun showCharacter(id: Campaign.CharacterInstance.Id) {
@ -59,4 +75,10 @@ class CharacterDetailViewModel(
fun hideCharacter() { fun hideCharacter() {
displayedCharacterId.value = null displayedCharacterId.value = null
} }
private fun empty() = CharacterDetailPanelUio(
characterInstanceId = null,
header = MutableStateFlow(null),
sheet = MutableStateFlow(null),
)
} }

View file

@ -20,14 +20,16 @@ class CharacterDiminishedViewModel(
val diminishedDialog: State<DiminishedStatDialogUio?> get() = _diminishedDialog val diminishedDialog: State<DiminishedStatDialogUio?> get() = _diminishedDialog
suspend fun showDiminishedDialog( suspend fun showDiminishedDialog(
id: Campaign.CharacterInstance.Id, characterInstanceId: Campaign.CharacterInstance.Id?,
) { ) {
if (characterInstanceId == null) return
val diminished = 0 // TODO repository.characterDiminishedFlow(id = id).value val diminished = 0 // TODO repository.characterDiminishedFlow(id = id).value
val textFieldValue = mutableStateOf( val textFieldValue = mutableStateOf(
TextFieldValue("$diminished", selection = TextRange(index = 0)) TextFieldValue("$diminished", selection = TextRange(index = 0))
) )
_diminishedDialog.value = DiminishedStatDialogUio( _diminishedDialog.value = DiminishedStatDialogUio(
id = id, id = characterInstanceId,
label = getString(resource = Res.string.character_sheet__diminished__label), label = getString(resource = Res.string.character_sheet__diminished__label),
value = { textFieldValue.value }, value = { textFieldValue.value },
onValueChange = { value -> onValueChange = { value ->
@ -51,6 +53,4 @@ class CharacterDiminishedViewModel(
// diminished = value, // diminished = value,
// ) // )
} }
} }

View file

@ -0,0 +1,156 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.header
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
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.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.draw.clip
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.shared.lwa.model.campaign.Campaign
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.ic_close_24dp
import lwacharactersheet.composeapp.generated.resources.ic_heart_24dp
import lwacharactersheet.composeapp.generated.resources.ic_near_me
import lwacharactersheet.composeapp.generated.resources.ic_skull_24dp
import lwacharactersheet.composeapp.generated.resources.ic_water_drop_24dp
import org.jetbrains.compose.resources.painterResource
@Stable
data class CharacterDetailHeaderUio(
val id: Campaign.CharacterInstance.Id,
val portrait: String?,
val name: String,
val hp: String,
val maxHp: String,
val pp: String,
val maxPp: String,
val mov: String,
)
@Composable
fun CharacterDetailHeader(
modifier: Modifier = Modifier,
header: State<CharacterDetailHeaderUio?>,
onDismissRequest: () -> Unit,
onDiminished: () -> Unit,
onHp: () -> Unit,
onPp: () -> Unit,
) {
Column(
modifier = modifier,
) {
Row {
Text(
modifier = Modifier.weight(1f)
.align(alignment = Alignment.CenterVertically),
style = MaterialTheme.typography.h5,
text = header.value?.name ?: "",
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
IconButton(
onClick = onDiminished,
) {
Icon(
modifier = Modifier.size(size = 24.dp),
painter = painterResource(Res.drawable.ic_skull_24dp),
tint = MaterialTheme.colors.primary,
contentDescription = null,
)
}
IconButton(
onClick = onDismissRequest,
) {
Icon(
painter = painterResource(Res.drawable.ic_close_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null,
)
}
}
Row(
horizontalArrangement = Arrangement.spacedBy(space = 12.dp),
) {
Row(
modifier = Modifier.clip(shape = CircleShape).clickable { onHp() },
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_heart_24dp),
contentDescription = null
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
color = MaterialTheme.lwa.colorScheme.base.primary,
fontWeight = FontWeight.Bold,
text = header.value?.hp ?: "",
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Thin,
text = "/${header.value?.maxHp ?: ""}",
)
}
Row(
modifier = Modifier.clip(shape = CircleShape).clickable { onPp() },
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_water_drop_24dp),
contentDescription = null
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
color = MaterialTheme.lwa.colorScheme.base.primary,
fontWeight = FontWeight.Bold,
text = header.value?.pp ?: "",
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
fontWeight = FontWeight.Thin,
text = "/${header.value?.maxPp ?: ""}",
)
}
Row(
verticalAlignment = Alignment.Bottom,
) {
Icon(
modifier = Modifier.padding(bottom = 4.dp, end = 2.dp).size(12.dp),
painter = painterResource(Res.drawable.ic_near_me),
contentDescription = null,
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.h6,
text = header.value?.mov ?: "",
)
Text(
modifier = Modifier.alignByBaseline(),
style = MaterialTheme.typography.caption,
text = "m",
)
}
}
}
}

View file

@ -0,0 +1,61 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.padding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipLayout
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipUio
@Stable
data class CharacterDetailSheetCharacteristicUio(
val value: String,
val label: String,
val tooltips: TooltipUio?,
)
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun CharacterDetailSheetCharacteristic(
modifier: Modifier = Modifier,
paddingValues: PaddingValues = PaddingValues(all = 8.dp),
characteristic: CharacterDetailSheetCharacteristicUio,
onClick: () -> Unit,
) {
TooltipLayout(
tooltip = characteristic.tooltips,
content = {
DecoratedBox(
modifier = Modifier
.clickable(onClick = onClick)
.padding(paddingValues = paddingValues)
.then(other = modifier),
) {
Text(
modifier = Modifier.align(alignment = Alignment.TopCenter),
style = MaterialTheme.typography.caption,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
text = characteristic.label,
)
Text(
modifier = Modifier.align(alignment = Alignment.Center),
style = MaterialTheme.typography.h3,
overflow = TextOverflow.Ellipsis,
maxLines = 1,
color = MaterialTheme.colors.primary,
text = characteristic.value
)
}
},
)
}

View file

@ -0,0 +1,47 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.sheet
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.size
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.pixelized.shared.lwa.model.campaign.Campaign
@Stable
data class CharacterDetailSheetUio(
val characterInstanceId: Campaign.CharacterInstance.Id,
val characteristics: List<CharacterDetailSheetCharacteristicUio>,
)
@Composable
fun CharacterDetailSheet(
modifier: Modifier = Modifier,
sheet: State<CharacterDetailSheetUio?>,
onCharacteristic: (CharacterDetailSheetCharacteristicUio) -> Unit,
) {
Row(
modifier = modifier
) {
Column(
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
) {
sheet.value?.characteristics?.forEach {
CharacterDetailSheetCharacteristic(
modifier = Modifier.size(width = 80.dp, height = 120.dp),
characteristic = it,
onClick = { onCharacteristic(it) },
)
}
}
Column(
verticalArrangement = Arrangement.spacedBy(space = 8.dp)
) {
}
}
}

View file

@ -6,13 +6,13 @@ import androidx.compose.animation.core.spring
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.pixelized.shared.lwa.usecase.ExpressionUseCase
import com.pixelized.shared.lwa.usecase.SkillStepUseCase
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 com.pixelized.desktop.lwa.repository.roll_history.RollHistoryRepository
import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio import com.pixelized.desktop.lwa.ui.screen.characterSheet.detail.CharacterSheetPageUio
import com.pixelized.desktop.lwa.ui.screen.roll.DifficultyUio.Difficulty import com.pixelized.desktop.lwa.ui.screen.roll.DifficultyUio.Difficulty
import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet import com.pixelized.shared.lwa.model.characterSheet.CharacterSheet
import com.pixelized.shared.lwa.usecase.ExpressionUseCase
import com.pixelized.shared.lwa.usecase.SkillStepUseCase
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -55,13 +55,17 @@ class RollViewModel(
private val _rollDifficulty = mutableStateOf<DifficultyUio?>(null) private val _rollDifficulty = mutableStateOf<DifficultyUio?>(null)
val rollDifficulty: State<DifficultyUio?> get() = _rollDifficulty val rollDifficulty: State<DifficultyUio?> get() = _rollDifficulty
private val _displayOverlay = mutableStateOf(false)
val displayOverlay: State<Boolean> get() = _displayOverlay
fun prepareRoll( fun prepareRoll(
sheet: CharacterSheetPageUio, sheet: CharacterSheetPageUio,
characteristic: CharacterSheetPageUio.Characteristic, characteristic: CharacterSheetPageUio.Characteristic,
) { ) {
val diminished = 0 // TODO characterSheetRepository.characterDiminishedFlow(id = sheet.id).value val diminished =
0 // TODO characterSheetRepository.characterDiminishedFlow(id = sheet.id).value
prepareRoll( prepareRoll(
sheet = sheet, characterSheetId = sheet.id,
label = characteristic.label, label = characteristic.label,
rollAction = "1d100", rollAction = "1d100",
rollSuccessValue = (characteristic.value.toIntOrNull() ?: 0) * 5 - diminished, rollSuccessValue = (characteristic.value.toIntOrNull() ?: 0) * 5 - diminished,
@ -73,7 +77,7 @@ class RollViewModel(
node: CharacterSheetPageUio.Node, node: CharacterSheetPageUio.Node,
) { ) {
prepareRoll( prepareRoll(
sheet = sheet, characterSheetId = sheet.id,
label = node.label, label = node.label,
rollAction = "1d100", rollAction = "1d100",
rollSuccessValue = node.value, rollSuccessValue = node.value,
@ -85,15 +89,15 @@ class RollViewModel(
roll: CharacterSheetPageUio.Roll, roll: CharacterSheetPageUio.Roll,
) { ) {
prepareRoll( prepareRoll(
sheet = sheet, characterSheetId = sheet.id,
label = roll.label, label = roll.label,
rollAction = roll.value, rollAction = roll.value,
rollSuccessValue = null, rollSuccessValue = null,
) )
} }
private fun prepareRoll( fun prepareRoll(
sheet: CharacterSheetPageUio, characterSheetId: String,
label: String, label: String,
rollAction: String, rollAction: String,
rollSuccessValue: Int?, rollSuccessValue: Int?,
@ -101,7 +105,7 @@ class RollViewModel(
this.sheet = runBlocking { this.sheet = runBlocking {
rollRotation.snapTo(0f) rollRotation.snapTo(0f)
rollScale.snapTo(1f) rollScale.snapTo(1f)
characterSheetRepository.characterDetail(characterSheetId = sheet.id)!! characterSheetRepository.characterDetail(characterSheetId = characterSheetId)!!
} }
this.rollAction = rollAction this.rollAction = rollAction
@ -238,4 +242,12 @@ class RollViewModel(
value = rollStep?.success?.last value = rollStep?.success?.last
) )
} }
fun showOverlay() {
_displayOverlay.value = true
}
fun hideOverlay() {
_displayOverlay.value = false
}
} }

View file

@ -59,7 +59,7 @@ class RollUseCase {
if (quantity > 1 && left != 1) print(",") if (quantity > 1 && left != 1) print(",")
} }
}.also { }.also {
print("}") println("}")
} }
} }