Add client inventory sheet management.
This commit is contained in:
parent
8982bab22d
commit
05a376aea8
10 changed files with 325 additions and 118 deletions
|
|
@ -184,6 +184,8 @@
|
|||
<string name="character_sheet__delete_dialog__title">Supprimer la feuille de personnage</string>
|
||||
<string name="character_sheet__delete_dialog__description">Êtes-vous sûr de vouloir supprimer "%1$s" ?</string>
|
||||
|
||||
<string name="character__inventory__add_to_inventory__action">Ajouter un objet</string>
|
||||
<string name="character__inventory__filter_inventory__label">Filtrer l'inventaire</string>
|
||||
<string name="character__inventory__add_to_purse__title">Ajouter à la bourse</string>
|
||||
<string name="character__inventory__remove_from_purse__title">Retirer de la bourse</string>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,29 +1,26 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
import androidx.compose.animation.ContentTransform
|
||||
import androidx.compose.animation.SizeTransform
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
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.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
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.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Button
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Add
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.State
|
||||
|
|
@ -31,45 +28,57 @@ import androidx.compose.runtime.collectAsState
|
|||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.LocalBlurController
|
||||
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialog
|
||||
import com.pixelized.desktop.lwa.ui.composable.character.purse.PurseDialogViewModel
|
||||
import com.pixelized.desktop.lwa.ui.composable.error.ErrorSnackHandler
|
||||
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextField
|
||||
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.InventoryItem
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.InventoryItemUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.InventoryPurse
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.PurseUio
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaTextFieldColors
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import com.pixelized.desktop.lwa.utils.extention.plus
|
||||
import kotlinx.coroutines.launch
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_copper_32px
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_gold_32px
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_silver_32px
|
||||
import lwacharactersheet.composeapp.generated.resources.character__inventory__add_to_inventory__action
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import org.jetbrains.compose.resources.stringResource
|
||||
import org.koin.compose.viewmodel.koinViewModel
|
||||
|
||||
@Stable
|
||||
data class CharacterDetailInventoryUio(
|
||||
val characterSheetId: String,
|
||||
val filter: LwaTextFieldUio,
|
||||
val purse: PurseUio,
|
||||
val items: List<InventoryItemUio>,
|
||||
) {
|
||||
@Stable
|
||||
data class PurseUio(
|
||||
val gold: Int,
|
||||
val silver: Int,
|
||||
val copper: Int,
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
@Stable
|
||||
object CharacterDetailInventoryDefault {
|
||||
val padding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
|
||||
@Stable
|
||||
val padding = PaddingValues(
|
||||
start = 16.dp,
|
||||
end = 16.dp,
|
||||
top = 8.dp,
|
||||
bottom = 8.dp,
|
||||
)
|
||||
|
||||
@Stable
|
||||
val spacing: Dp = 8.dp
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun CharacterDetailInventory(
|
||||
modifier: Modifier = Modifier,
|
||||
paddings: PaddingValues = CharacterDetailInventoryDefault.padding,
|
||||
spacing: Dp = CharacterDetailInventoryDefault.spacing,
|
||||
purseViewModel: PurseDialogViewModel = koinViewModel(),
|
||||
inventory: State<CharacterDetailInventoryUio?>,
|
||||
) {
|
||||
|
|
@ -82,6 +91,7 @@ fun CharacterDetailInventory(
|
|||
else -> CharacterDetailInventoryContent(
|
||||
modifier = modifier,
|
||||
paddings = paddings,
|
||||
spacing = spacing,
|
||||
inventory = unWrap,
|
||||
onPurse = {
|
||||
blur.show()
|
||||
|
|
@ -118,119 +128,95 @@ fun CharacterDetailInventory(
|
|||
private fun CharacterDetailInventoryContent(
|
||||
modifier: Modifier = Modifier,
|
||||
paddings: PaddingValues,
|
||||
spacing: Dp,
|
||||
inventory: CharacterDetailInventoryUio,
|
||||
onPurse: (String) -> Unit,
|
||||
) {
|
||||
Column(
|
||||
Box(
|
||||
modifier = modifier,
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.weight(1f),
|
||||
contentPadding = paddings,
|
||||
modifier = Modifier.matchParentSize(),
|
||||
contentPadding = paddings + PaddingValues(bottom = 56.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(space = spacing),
|
||||
) {
|
||||
item(
|
||||
key = "purse",
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.Bottom,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = spacing),
|
||||
) {
|
||||
InventoryPurse(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
purse = inventory.purse,
|
||||
onPurse = { onPurse(inventory.characterSheetId) },
|
||||
)
|
||||
LwaTextField(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
colors = LwaTextFieldColors(
|
||||
backgroundColor = MaterialTheme.lwa.colorScheme.elevated.base2dp,
|
||||
),
|
||||
field = inventory.filter,
|
||||
trailingIcon = {
|
||||
val value = inventory.filter.valueFlow.collectAsState()
|
||||
AnimatedVisibility(
|
||||
visible = value.value.isNotBlank(),
|
||||
enter = fadeIn(),
|
||||
exit = fadeOut(),
|
||||
) {
|
||||
IconButton(
|
||||
onClick = { inventory.filter.onValueChange.invoke("") },
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(Res.drawable.ic_cancel_24dp),
|
||||
tint = MaterialTheme.lwa.colorScheme.base.primary,
|
||||
contentDescription = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
items(
|
||||
items = inventory.items,
|
||||
key = { it.inventoryId },
|
||||
) {
|
||||
InventoryItem(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
modifier = Modifier
|
||||
.animateItem()
|
||||
.fillMaxWidth(),
|
||||
item = it,
|
||||
onClick = { },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Purse(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
paddings = paddings,
|
||||
purse = inventory.purse,
|
||||
onPurse = { onPurse(inventory.characterSheetId) },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Purse(
|
||||
modifier: Modifier = Modifier,
|
||||
paddings: PaddingValues,
|
||||
purse: CharacterDetailInventoryUio.PurseUio,
|
||||
onPurse: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.background(color = MaterialTheme.lwa.colorScheme.elevated.base2dp)
|
||||
.then(other = modifier),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.End,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable { onPurse() }
|
||||
.align(alignment = Alignment.BottomEnd)
|
||||
.padding(paddingValues = paddings),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_gold_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
Button(
|
||||
colors = LwaButtonColors(),
|
||||
elevation = ButtonDefaults.elevation(4.dp),
|
||||
shape = CircleShape,
|
||||
onClick = { },
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(end = 4.dp),
|
||||
text = stringResource(Res.string.character__inventory__add_to_inventory__action),
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.Add,
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.gold,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_silver_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.silver,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_copper_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.copper,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
private fun coinTransitionSpec(): AnimatedContentTransitionScope<Int>.() -> ContentTransform = {
|
||||
val enter = fadeIn() + slideInVertically { -16 }
|
||||
val exit = fadeOut() + slideOutVertically { 16 }
|
||||
enter togetherWith exit using SizeTransform(clip = false)
|
||||
}
|
||||
|
|
@ -2,35 +2,55 @@ package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory
|
|||
|
||||
import com.pixelized.desktop.lwa.repository.inventory.InventoryRepository
|
||||
import com.pixelized.desktop.lwa.repository.item.ItemRepository
|
||||
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.InventoryItemUio
|
||||
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item.PurseUio
|
||||
import com.pixelized.desktop.lwa.utils.extention.unAccent
|
||||
import com.pixelized.shared.lwa.model.inventory.Inventory
|
||||
import com.pixelized.shared.lwa.model.item.Item
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.character__inventory__filter_inventory__label
|
||||
import org.jetbrains.compose.resources.getString
|
||||
import java.text.Collator
|
||||
|
||||
class CharacterDetailInventoryFactory(
|
||||
private val inventoryRepository: InventoryRepository,
|
||||
private val itemRepository: ItemRepository,
|
||||
) {
|
||||
|
||||
fun convertToCharacterInventoryUioFlow(
|
||||
suspend fun convertToCharacterInventoryUioFlow(
|
||||
characterSheetId: String,
|
||||
scope: CoroutineScope,
|
||||
started: SharingStarted = SharingStarted.Eagerly,
|
||||
initialValue: () -> CharacterDetailInventoryUio?,
|
||||
): StateFlow<CharacterDetailInventoryUio?> {
|
||||
val filterFlow = MutableStateFlow("")
|
||||
val filterField = LwaTextFieldUio(
|
||||
enable = true,
|
||||
isError = MutableStateFlow(false),
|
||||
valueFlow = filterFlow,
|
||||
label = getString(Res.string.character__inventory__filter_inventory__label),
|
||||
placeHolder = null,
|
||||
onValueChange = { filterFlow.value = it },
|
||||
)
|
||||
return combine(
|
||||
inventoryRepository.inventoryFlow(characterSheetId = characterSheetId),
|
||||
itemRepository.itemFlow,
|
||||
) { inventory, items ->
|
||||
filterFlow.map { it.unAccent() },
|
||||
) { inventory, items, filter ->
|
||||
convertToCharacterInventoryUio(
|
||||
characterSheetId = characterSheetId,
|
||||
filter = filterField,
|
||||
purse = inventory?.purse,
|
||||
inventory = inventory?.items,
|
||||
items = items,
|
||||
items = items.filterValues { it.metadata.name.unAccent().contains(filter, true) },
|
||||
)
|
||||
}.stateIn(
|
||||
scope = scope,
|
||||
|
|
@ -41,6 +61,7 @@ class CharacterDetailInventoryFactory(
|
|||
|
||||
private suspend fun convertToCharacterInventoryUio(
|
||||
characterSheetId: String?,
|
||||
filter: LwaTextFieldUio,
|
||||
purse: Inventory.Purse?,
|
||||
inventory: List<Inventory.Item>?,
|
||||
items: Map<String, Item>,
|
||||
|
|
@ -49,19 +70,22 @@ class CharacterDetailInventoryFactory(
|
|||
|
||||
return CharacterDetailInventoryUio(
|
||||
characterSheetId = characterSheetId,
|
||||
purse = CharacterDetailInventoryUio.PurseUio(
|
||||
purse = PurseUio(
|
||||
gold = purse?.gold ?: 0,
|
||||
silver = purse?.silver ?: 0,
|
||||
copper = purse?.copper ?: 0,
|
||||
),
|
||||
filter = filter,
|
||||
items = inventory
|
||||
?.mapNotNull {
|
||||
val label = items[it.itemId]?.metadata?.name ?: return@mapNotNull null
|
||||
InventoryItemUio(
|
||||
inventoryId = it.inventoryId,
|
||||
label = label,
|
||||
equipped = it.equipped,
|
||||
)
|
||||
}
|
||||
?.sortedWith(compareBy(Collator.getInstance()) { it.label })
|
||||
?: emptyList()
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,13 +12,16 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import com.pixelized.desktop.lwa.utils.extention.ribbon
|
||||
|
||||
@Stable
|
||||
data class InventoryItemUio(
|
||||
val inventoryId: String,
|
||||
val label: String,
|
||||
val equipped: Boolean,
|
||||
)
|
||||
|
||||
@Stable
|
||||
|
|
@ -36,9 +39,15 @@ fun InventoryItem(
|
|||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(shape = MaterialTheme.lwa.shapes.gameMaster)
|
||||
.clip(shape = MaterialTheme.lwa.shapes.item)
|
||||
.clickable(onClick = onClick)
|
||||
.background(color = MaterialTheme.lwa.colorScheme.elevated.base2dp)
|
||||
.ribbon(
|
||||
color = when (item.equipped) {
|
||||
true -> MaterialTheme.lwa.colorScheme.base.primary
|
||||
else -> Color.Transparent
|
||||
}
|
||||
)
|
||||
.minimumInteractiveComponentSize()
|
||||
.padding(paddingValues = padding)
|
||||
.then(other = modifier),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item
|
||||
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||
import androidx.compose.animation.ContentTransform
|
||||
import androidx.compose.animation.SizeTransform
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
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.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.draw.clip
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_copper_32px
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_gold_32px
|
||||
import lwacharactersheet.composeapp.generated.resources.ic_silver_32px
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
|
||||
@Stable
|
||||
data class PurseUio(
|
||||
val gold: Int,
|
||||
val silver: Int,
|
||||
val copper: Int,
|
||||
)
|
||||
|
||||
@Stable
|
||||
object InventoryPurseDefault {
|
||||
@Stable
|
||||
val paddings = PaddingValues(horizontal = 0.dp, vertical = 4.dp)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun InventoryPurse(
|
||||
modifier: Modifier = Modifier,
|
||||
paddings: PaddingValues = InventoryPurseDefault.paddings,
|
||||
purse: PurseUio,
|
||||
onPurse: () -> Unit,
|
||||
) {
|
||||
Row(
|
||||
modifier = modifier,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Start,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clip(shape = MaterialTheme.lwa.shapes.item)
|
||||
.clickable { onPurse() }
|
||||
.padding(paddingValues = paddings),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
|
||||
) {
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_gold_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.gold,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_silver_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.silver,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Row(verticalAlignment = Alignment.Bottom) {
|
||||
Image(
|
||||
painter = painterResource(Res.drawable.ic_copper_32px),
|
||||
modifier = Modifier.padding(bottom = 2.dp).size(size = 16.dp),
|
||||
contentDescription = null,
|
||||
)
|
||||
AnimatedContent(
|
||||
targetState = purse.copper,
|
||||
transitionSpec = coinTransitionSpec(),
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
text = "$it",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Stable
|
||||
private fun coinTransitionSpec(): AnimatedContentTransitionScope<Int>.() -> ContentTransform = {
|
||||
val enter = fadeIn() + slideInHorizontally { -16 }
|
||||
val exit = fadeOut() + slideOutHorizontally { 16 }
|
||||
enter togetherWith exit using SizeTransform(clip = false)
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package com.pixelized.desktop.lwa.utils.extention
|
||||
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
||||
fun Modifier.ribbon(
|
||||
width: Dp = 4.dp,
|
||||
color: Color,
|
||||
): Modifier = composed {
|
||||
val animatedColor = animateColorAsState(
|
||||
targetValue = color,
|
||||
)
|
||||
return@composed drawWithContent {
|
||||
drawContent()
|
||||
drawRect(
|
||||
color = animatedColor.value,
|
||||
size = Size(
|
||||
width = width.toPx(),
|
||||
height = size.height,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
package com.pixelized.desktop.lwa.utils.extention
|
||||
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.calculateStartPadding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
|
||||
@Stable
|
||||
@Composable
|
||||
operator fun PaddingValues.plus(other: PaddingValues): PaddingValues {
|
||||
val direction = LocalLayoutDirection.current
|
||||
return remember(this, other, direction) {
|
||||
PaddingValues(
|
||||
start = calculateStartPadding(direction) + other.calculateStartPadding(direction),
|
||||
top = calculateTopPadding() + other.calculateTopPadding(),
|
||||
end = calculateEndPadding(direction) + other.calculateEndPadding(direction),
|
||||
bottom = calculateBottomPadding() + other.calculateBottomPadding(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ data class Inventory(
|
|||
val inventoryId: String,
|
||||
val itemId: String,
|
||||
val count: Int,
|
||||
val equipped: Boolean,
|
||||
)
|
||||
|
||||
companion object {
|
||||
|
|
|
|||
|
|
@ -21,5 +21,6 @@ data class InventoryJsonV1(
|
|||
val inventoryId: String,
|
||||
val itemId: String,
|
||||
val count: Int,
|
||||
val equipped: Boolean?,
|
||||
)
|
||||
}
|
||||
|
|
@ -18,6 +18,7 @@ class InventoryJsonFactoryV1 {
|
|||
inventoryId = it.inventoryId,
|
||||
itemId = it.itemId,
|
||||
count = it.count,
|
||||
equipped = it.equipped ?: false,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
@ -36,6 +37,7 @@ class InventoryJsonFactoryV1 {
|
|||
inventoryId = it.inventoryId,
|
||||
itemId = it.itemId,
|
||||
count = it.count,
|
||||
equipped = it.equipped,
|
||||
)
|
||||
},
|
||||
)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue