Add a filter button on the player inventory.

This commit is contained in:
Andres Gomez, Thomas (ITDV RL) 2025-05-12 11:06:48 +02:00
parent 2c4519af3b
commit 5632ec7c85
4 changed files with 114 additions and 79 deletions

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#000000"
android:pathData="M400,720L400,640L560,640L560,720L400,720ZM240,520L240,440L720,440L720,520L240,520ZM120,320L120,240L840,240L840,320L120,320Z" />
</vector>

View file

@ -1,16 +1,23 @@
package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory package com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory
import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut import androidx.compose.animation.fadeOut
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.IntrinsicSize
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.calculateEndPadding import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
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.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
@ -22,6 +29,7 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.AddCircle
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.State
@ -32,6 +40,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope 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.draw.clip
import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
@ -53,11 +62,13 @@ import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.inventory.item
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors 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.color.component.LwaTextFieldColors
import com.pixelized.desktop.lwa.ui.theme.lwa import com.pixelized.desktop.lwa.ui.theme.lwa
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.character__inventory__add_to_inventory__action import lwacharactersheet.composeapp.generated.resources.character__inventory__add_to_inventory__action
import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp import lwacharactersheet.composeapp.generated.resources.ic_cancel_24dp
import lwacharactersheet.composeapp.generated.resources.ic_filter_list_24dp
import org.jetbrains.compose.resources.painterResource import org.jetbrains.compose.resources.painterResource
import org.jetbrains.compose.resources.stringResource import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel import org.koin.compose.viewmodel.koinViewModel
@ -66,6 +77,7 @@ import org.koin.compose.viewmodel.koinViewModel
data class CharacterDetailInventoryUio( data class CharacterDetailInventoryUio(
val characterSheetId: String, val characterSheetId: String,
val addItemAction: StateFlow<Boolean>, val addItemAction: StateFlow<Boolean>,
val showFilter: StateFlow<Boolean>,
val filter: LwaTextFieldUio, val filter: LwaTextFieldUio,
val purse: PurseUio, val purse: PurseUio,
val items: List<InventoryItemUio>, val items: List<InventoryItemUio>,
@ -292,35 +304,56 @@ private fun CharacterDetailInventoryContent(
horizontalArrangement = Arrangement.spacedBy(space = spacing), horizontalArrangement = Arrangement.spacedBy(space = spacing),
) { ) {
InventoryPurse( InventoryPurse(
modifier = Modifier.weight(weight = 1f),
purse = inventory.purse, purse = inventory.purse,
onPurse = { onPurse(inventory.characterSheetId) }, onPurse = { onPurse(inventory.characterSheetId) },
) )
LwaTextField( Spacer(
modifier = Modifier.weight(weight = 1f), modifier = Modifier.weight(weight = 1f)
colors = LwaTextFieldColors( )
backgroundColor = MaterialTheme.lwa.colorScheme.elevated.base2dp, AnimatedContent(
), targetState = inventory.showFilter.collectAsState().value,
field = inventory.filter, ) {
trailingIcon = { when (it) {
val value = inventory.filter.valueFlow.collectAsState() true -> LwaTextField(
AnimatedVisibility( colors = LwaTextFieldColors(
visible = value.value.isNotBlank(), backgroundColor = MaterialTheme.lwa.colorScheme.elevated.base2dp,
enter = fadeIn(), ),
exit = fadeOut(), field = inventory.filter,
) { trailingIcon = {
IconButton( val value = inventory.filter.valueFlow.collectAsState()
onClick = { inventory.filter.onValueChange.invoke("") }, androidx.compose.animation.AnimatedVisibility(
) { visible = value.value.isNotBlank(),
Icon( enter = fadeIn(),
painter = painterResource(Res.drawable.ic_cancel_24dp), exit = fadeOut(),
tint = MaterialTheme.lwa.colorScheme.base.primary, ) {
contentDescription = null, IconButton(
) onClick = { inventory.filter.onValueChange.invoke("") },
) {
Icon(
painter = painterResource(Res.drawable.ic_cancel_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null,
)
}
}
} }
)
else -> Box(
modifier = Modifier
.clip(shape = MaterialTheme.lwa.shapes.base.small)
.clickable { (inventory.showFilter as? MutableStateFlow<Boolean>)?.value = true }
.size(size = 32.dp),
contentAlignment = Alignment.Center,
) {
Icon(
painter = painterResource(Res.drawable.ic_filter_list_24dp),
tint = MaterialTheme.lwa.colorScheme.base.primary,
contentDescription = null
)
} }
} }
) }
} }
} }
items( items(

View file

@ -13,6 +13,7 @@ import com.pixelized.shared.lwa.model.inventory.Inventory
import com.pixelized.shared.lwa.model.item.Item import com.pixelized.shared.lwa.model.item.Item
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
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
@ -45,6 +46,7 @@ class CharacterDetailInventoryFactory(
addItemAction: StateFlow<Boolean>, addItemAction: StateFlow<Boolean>,
initialValue: () -> CharacterDetailInventoryUio?, initialValue: () -> CharacterDetailInventoryUio?,
): StateFlow<CharacterDetailInventoryUio?> { ): StateFlow<CharacterDetailInventoryUio?> {
val showFilterFlow = MutableStateFlow(false)
val filterFlow = createLwaTextFieldFlow( val filterFlow = createLwaTextFieldFlow(
label = getString(Res.string.character__inventory__filter_inventory__label), label = getString(Res.string.character__inventory__filter_inventory__label),
value = "", value = "",
@ -56,6 +58,7 @@ class CharacterDetailInventoryFactory(
) { inventory, items, filter -> ) { inventory, items, filter ->
convertToCharacterInventoryUio( convertToCharacterInventoryUio(
characterSheetId = characterSheetId, characterSheetId = characterSheetId,
showFilter = showFilterFlow,
filter = filterFlow.createLwaTextField(), filter = filterFlow.createLwaTextField(),
addItemAction = addItemAction, addItemAction = addItemAction,
purse = inventory.purse, purse = inventory.purse,
@ -71,6 +74,7 @@ class CharacterDetailInventoryFactory(
private fun convertToCharacterInventoryUio( private fun convertToCharacterInventoryUio(
characterSheetId: String?, characterSheetId: String?,
showFilter: StateFlow<Boolean>,
filter: LwaTextFieldUio, filter: LwaTextFieldUio,
addItemAction: StateFlow<Boolean>, addItemAction: StateFlow<Boolean>,
purse: Inventory.Purse?, purse: Inventory.Purse?,
@ -86,6 +90,7 @@ class CharacterDetailInventoryFactory(
silver = purse?.silver ?: 0, silver = purse?.silver ?: 0,
copper = purse?.copper ?: 0, copper = purse?.copper ?: 0,
), ),
showFilter = showFilter,
filter = filter, filter = filter,
addItemAction = addItemAction, addItemAction = addItemAction,
items = inventory items = inventory

View file

@ -10,13 +10,11 @@ import androidx.compose.animation.slideInHorizontally
import androidx.compose.animation.slideOutHorizontally import androidx.compose.animation.slideOutHorizontally
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.Image
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -29,11 +27,6 @@ import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.composable.currency.Currency import com.pixelized.desktop.lwa.ui.composable.currency.Currency
import com.pixelized.desktop.lwa.ui.composable.currency.CurrencyUio import com.pixelized.desktop.lwa.ui.composable.currency.CurrencyUio
import com.pixelized.desktop.lwa.ui.theme.lwa 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 @Stable
data class PurseUio( data class PurseUio(
@ -57,63 +50,58 @@ fun InventoryPurse(
onPurse: () -> Unit, onPurse: () -> Unit,
) { ) {
Row( Row(
modifier = modifier, modifier = Modifier
verticalAlignment = Alignment.CenterVertically, .clip(shape = MaterialTheme.lwa.shapes.item)
horizontalArrangement = Arrangement.Start, .clickable { onPurse() }
.padding(paddingValues = paddings)
.then(other = modifier),
horizontalArrangement = Arrangement.spacedBy(space = 8.dp),
) { ) {
Row( Row(verticalAlignment = Alignment.Bottom) {
modifier = Modifier Currency(
.clip(shape = MaterialTheme.lwa.shapes.item) currency = CurrencyUio.Gold,
.clickable { onPurse() } )
.padding(paddingValues = paddings), AnimatedContent(
horizontalArrangement = Arrangement.spacedBy(space = 8.dp), targetState = purse.gold,
) { transitionSpec = coinTransitionSpec(),
Row(verticalAlignment = Alignment.Bottom) { ) {
Currency( Text(
currency = CurrencyUio.Gold, style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
) )
AnimatedContent(
targetState = purse.gold,
transitionSpec = coinTransitionSpec(),
) {
Text(
style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
)
}
} }
}
Row(verticalAlignment = Alignment.Bottom) { Row(verticalAlignment = Alignment.Bottom) {
Currency( Currency(
currency = CurrencyUio.Silver, currency = CurrencyUio.Silver,
)
AnimatedContent(
targetState = purse.silver,
transitionSpec = coinTransitionSpec(),
) {
Text(
style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
) )
AnimatedContent(
targetState = purse.silver,
transitionSpec = coinTransitionSpec(),
) {
Text(
style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
)
}
} }
}
Row(verticalAlignment = Alignment.Bottom) { Row(verticalAlignment = Alignment.Bottom) {
Currency( Currency(
currency = CurrencyUio.Copper, currency = CurrencyUio.Copper,
)
AnimatedContent(
targetState = purse.copper,
transitionSpec = coinTransitionSpec(),
) {
Text(
style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
) )
AnimatedContent(
targetState = purse.copper,
transitionSpec = coinTransitionSpec(),
) {
Text(
style = MaterialTheme.lwa.typography.system.body1,
fontWeight = FontWeight.Bold,
text = "$it",
)
}
} }
} }
} }