Change the UI of the InventoryItem.
This commit is contained in:
parent
fa49d8ed22
commit
898a8862db
7 changed files with 169 additions and 46 deletions
|
|
@ -32,6 +32,7 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
|
@ -95,6 +96,7 @@ fun CharacterDetailInventory(
|
|||
inventory: State<CharacterDetailInventoryUio?>,
|
||||
) {
|
||||
val blur = LocalBlurController.current
|
||||
val focus = LocalFocusManager.current
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
when (val unWrap = inventory.value) {
|
||||
|
|
@ -110,6 +112,7 @@ fun CharacterDetailInventory(
|
|||
purseViewModel.showPurseDialog(
|
||||
characterSheetId = it,
|
||||
)
|
||||
focus.clearFocus(force = true)
|
||||
},
|
||||
onItem = { item ->
|
||||
blur.show()
|
||||
|
|
@ -118,12 +121,14 @@ fun CharacterDetailInventory(
|
|||
inventoryId = item.inventoryId,
|
||||
itemId = item.itemId,
|
||||
)
|
||||
focus.clearFocus(force = true)
|
||||
},
|
||||
onAddItem = {
|
||||
blur.show()
|
||||
inventoryDialogViewModel.showInventoryDialog(
|
||||
characterSheetId = it,
|
||||
)
|
||||
focus.clearFocus(force = true)
|
||||
},
|
||||
onConsume = {
|
||||
scope.launch {
|
||||
|
|
@ -132,6 +137,7 @@ fun CharacterDetailInventory(
|
|||
inventoryId = it.inventoryId,
|
||||
)
|
||||
}
|
||||
focus.clearFocus(force = true)
|
||||
},
|
||||
onEquip = {
|
||||
scope.launch {
|
||||
|
|
@ -140,6 +146,7 @@ fun CharacterDetailInventory(
|
|||
inventoryId = it.inventoryId,
|
||||
)
|
||||
}
|
||||
focus.clearFocus(force = true)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ 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 org.koin.core.component.getScopeName
|
||||
import java.text.Collator
|
||||
import java.text.DecimalFormat
|
||||
|
||||
|
|
@ -96,6 +97,7 @@ class CharacterDetailInventoryFactory(
|
|||
characterSheetId = characterSheetId,
|
||||
inventoryId = it.inventoryId,
|
||||
itemId = it.itemId,
|
||||
icon = item.metadata.thumbnail,
|
||||
label = item.metadata.label,
|
||||
count = decimalFormat.format(it.count),
|
||||
equipped = it.equipped,
|
||||
|
|
@ -111,6 +113,7 @@ class CharacterDetailInventoryFactory(
|
|||
)
|
||||
}
|
||||
?.sortedWith(compareBy(Collator.getInstance()) { it.label })
|
||||
?.sortedByDescending { it.equipped }
|
||||
?: emptyList()
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import androidx.compose.animation.AnimatedContent
|
|||
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.slideInVertically
|
||||
import androidx.compose.animation.slideOutVertically
|
||||
import androidx.compose.animation.togetherWith
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.foundation.background
|
||||
|
|
@ -15,11 +15,14 @@ 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.calculateEndPadding
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.widthIn
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Surface
|
||||
import androidx.compose.material.Text
|
||||
|
|
@ -27,22 +30,24 @@ import androidx.compose.material.TextButton
|
|||
import androidx.compose.material.minimumInteractiveComponentSize
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.FilterQuality
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.layout.ContentScale
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
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.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import coil3.compose.AsyncImage
|
||||
import com.pixelized.desktop.lwa.ui.composable.decoratedBox.DecoratedBox
|
||||
import com.pixelized.desktop.lwa.ui.composable.image.DesaturatedAsyncImage
|
||||
import com.pixelized.desktop.lwa.ui.composable.tooltip.TooltipLayout2
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
import com.pixelized.desktop.lwa.utils.extention.calculatePaddings
|
||||
import com.pixelized.desktop.lwa.utils.extention.ribbon
|
||||
import com.pixelized.desktop.lwa.utils.rememberSaturationFilter
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
|
|
@ -56,6 +61,7 @@ data class InventoryItemUio(
|
|||
val characterSheetId: String,
|
||||
val inventoryId: String,
|
||||
val itemId: String,
|
||||
val icon: String?,
|
||||
val label: String,
|
||||
val count: String,
|
||||
val equipped: Boolean,
|
||||
|
|
@ -74,11 +80,13 @@ data class InventoryItemUio(
|
|||
@Stable
|
||||
object GMCharacterPreviewDefault {
|
||||
@Stable
|
||||
val paddings = PaddingValues(horizontal = 16.dp)
|
||||
val paddings = PaddingValues(horizontal = 8.dp)
|
||||
|
||||
@Stable
|
||||
val toolTipPaddings = PaddingValues(all = 16.dp)
|
||||
|
||||
val icon: DpSize = DpSize(width = 32.dp, height = 32.dp)
|
||||
|
||||
@Stable
|
||||
val spacing: Dp = 8.dp
|
||||
}
|
||||
|
|
@ -90,17 +98,14 @@ fun InventoryItem(
|
|||
padding: PaddingValues = GMCharacterPreviewDefault.paddings,
|
||||
toolTipPaddings: PaddingValues = GMCharacterPreviewDefault.toolTipPaddings,
|
||||
spacing: Dp = GMCharacterPreviewDefault.spacing,
|
||||
icon: DpSize = GMCharacterPreviewDefault.icon,
|
||||
item: InventoryItemUio,
|
||||
onClick: () -> Unit,
|
||||
onConsume: () -> Unit,
|
||||
onEquip: () -> Unit,
|
||||
) {
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val toolTop = remember(toolTipPaddings) { toolTipPaddings.calculateTopPadding() }
|
||||
val toolEnd = remember(toolTipPaddings, layoutDirection) {
|
||||
toolTipPaddings.calculateEndPadding(layoutDirection)
|
||||
}
|
||||
val end = remember(padding, layoutDirection) { padding.calculateEndPadding(layoutDirection) }
|
||||
val (start, top, end, bottom) = padding.calculatePaddings()
|
||||
val (_, toolTop, toolEnd, _) = toolTipPaddings.calculatePaddings()
|
||||
|
||||
TooltipLayout2(
|
||||
modifier = modifier,
|
||||
|
|
@ -159,44 +164,84 @@ fun InventoryItem(
|
|||
)
|
||||
.minimumInteractiveComponentSize()
|
||||
.fillMaxWidth()
|
||||
.padding(paddingValues = padding)
|
||||
.padding(start = start, end = end)
|
||||
.then(other = modifier),
|
||||
horizontalArrangement = Arrangement.SpaceBetween,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = spacing / 2),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = spacing),
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.height(height = icon.height)
|
||||
.widthIn(min = icon.width, max = icon.width * 3)
|
||||
.graphicsLayer { clip = false },
|
||||
contentAlignment = Alignment.CenterStart,
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(size = icon)
|
||||
.background(
|
||||
color = MaterialTheme.lwa.colorScheme.elevated.base4dp,
|
||||
shape = CircleShape,
|
||||
)
|
||||
)
|
||||
AsyncImage(
|
||||
modifier = Modifier
|
||||
.size(size = icon)
|
||||
.aspectRatio(ratio = 1f, matchHeightConstraintsFirst = true),
|
||||
model = item.icon,
|
||||
contentScale = ContentScale.Crop,
|
||||
contentDescription = null,
|
||||
)
|
||||
if (item.consumable) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.BottomEnd)
|
||||
.offset(y = 4.dp),
|
||||
targetState = item.count,
|
||||
transitionSpec = {
|
||||
val enter = fadeIn() + slideInVertically { -8 }
|
||||
val exit = fadeOut() + slideOutVertically { 8 }
|
||||
enter togetherWith exit using SizeTransform(clip = false)
|
||||
},
|
||||
) {
|
||||
Box(
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.inventory.countOutline,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = it,
|
||||
)
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.inventory.countInline,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline().weight(weight = 1f, fill = false),
|
||||
style = MaterialTheme.lwa.typography.base.body1,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier
|
||||
.padding(top = top, bottom = bottom)
|
||||
.weight(weight = 1f, fill = false),
|
||||
style = MaterialTheme.lwa.typography.inventory.label,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = item.label,
|
||||
)
|
||||
if (item.consumable) {
|
||||
AnimatedContent(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
targetState = item.count,
|
||||
transitionSpec = {
|
||||
val enter = fadeIn() + slideInHorizontally { 16 }
|
||||
val exit = fadeOut() + slideOutHorizontally { -16 }
|
||||
enter togetherWith exit using SizeTransform(clip = false)
|
||||
},
|
||||
) {
|
||||
Text(
|
||||
style = MaterialTheme.lwa.typography.base.caption,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
Row(
|
||||
modifier = Modifier.offset(x = end - spacing),
|
||||
modifier = Modifier
|
||||
.padding(top = top, bottom = bottom)
|
||||
.offset(x = end - spacing),
|
||||
horizontalArrangement = Arrangement.spacedBy(space = spacing),
|
||||
) {
|
||||
if (item.consumable) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package com.pixelized.desktop.lwa.ui.theme
|
|||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.compositionLocalOf
|
||||
import androidx.compose.runtime.remember
|
||||
|
|
@ -20,8 +21,9 @@ val LocalLwaTheme = compositionLocalOf<LwaTheme> {
|
|||
}
|
||||
|
||||
val MaterialTheme.lwa: LwaTheme
|
||||
@Composable
|
||||
@Stable
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
get() = LocalLwaTheme.current
|
||||
|
||||
@Stable
|
||||
|
|
|
|||
|
|
@ -7,6 +7,9 @@ import androidx.compose.runtime.remember
|
|||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shadow
|
||||
import androidx.compose.ui.graphics.StrokeJoin
|
||||
import androidx.compose.ui.graphics.drawscope.Fill
|
||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontStyle
|
||||
|
|
@ -15,6 +18,7 @@ import androidx.compose.ui.text.style.TextAlign
|
|||
import androidx.compose.ui.unit.sp
|
||||
import com.pixelized.desktop.lwa.ui.theme.color.LwaColors
|
||||
import com.pixelized.desktop.lwa.ui.theme.typography.LwaTypography.Settings
|
||||
import com.pixelized.shared.lwa.model.inventory.Inventory
|
||||
import lwacharactersheet.composeapp.generated.resources.Res
|
||||
import lwacharactersheet.composeapp.generated.resources.consola_mono_bold
|
||||
import lwacharactersheet.composeapp.generated.resources.consola_mono_book
|
||||
|
|
@ -26,6 +30,7 @@ data class LwaTypography(
|
|||
val chat: Chat,
|
||||
val settings: Settings,
|
||||
val portrait: Portrait,
|
||||
val inventory: Inventory,
|
||||
) {
|
||||
@Stable
|
||||
data class Chat(
|
||||
|
|
@ -46,6 +51,13 @@ data class LwaTypography(
|
|||
val value: TextStyle,
|
||||
val max: TextStyle,
|
||||
)
|
||||
|
||||
@Stable
|
||||
data class Inventory(
|
||||
val countOutline: TextStyle,
|
||||
val countInline: TextStyle,
|
||||
val label: TextStyle,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -118,6 +130,25 @@ fun lwaTypography(
|
|||
blurRadius = 2f,
|
||||
),
|
||||
),
|
||||
),
|
||||
inventory = LwaTypography.Inventory(
|
||||
countOutline = base.caption.copy(
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = colors.elevated.base4dp,
|
||||
drawStyle = Stroke(
|
||||
miter = 3f,
|
||||
width = 3f,
|
||||
join = StrokeJoin.Round,
|
||||
)
|
||||
),
|
||||
countInline = base.caption.copy(
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
color = colors.base.onSurface,
|
||||
drawStyle = Fill
|
||||
),
|
||||
label = base.body1.copy(
|
||||
fontWeight = FontWeight.Normal,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
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.Immutable
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.LayoutDirection
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun PaddingValues.calculatePaddings(
|
||||
layoutDirection: LayoutDirection = LocalLayoutDirection.current,
|
||||
): ComputedPaddingValues {
|
||||
return ComputedPaddingValues(
|
||||
start = calculateStartPadding(layoutDirection = layoutDirection),
|
||||
top = calculateTopPadding(),
|
||||
end = calculateEndPadding(layoutDirection = layoutDirection),
|
||||
bottom = calculateBottomPadding(),
|
||||
)
|
||||
}
|
||||
|
||||
@Immutable
|
||||
@Stable
|
||||
data class ComputedPaddingValues(
|
||||
@Stable val start: Dp,
|
||||
@Stable val top: Dp,
|
||||
@Stable val end: Dp,
|
||||
@Stable val bottom: Dp,
|
||||
)
|
||||
|
|
@ -2,21 +2,22 @@ package com.pixelized.desktop.lwa.utils
|
|||
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.ReadOnlyComposable
|
||||
import androidx.compose.ui.graphics.Brush
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import com.pixelized.desktop.lwa.ui.theme.lwa
|
||||
|
||||
@Composable
|
||||
@ReadOnlyComposable
|
||||
fun rememberBackgroundGradient(
|
||||
color: Color = MaterialTheme.lwa.colorScheme.base.surface,
|
||||
from: Float = 0.5f,
|
||||
to: Float = 1.0f,
|
||||
): Brush {
|
||||
val colorScheme = MaterialTheme.colors
|
||||
return remember(colorScheme) {
|
||||
Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
colorScheme.surface.copy(alpha = from),
|
||||
colorScheme.surface.copy(alpha = to),
|
||||
)
|
||||
return Brush.verticalGradient(
|
||||
colors = listOf(
|
||||
color.copy(alpha = from),
|
||||
color.copy(alpha = to),
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue