Forbide multiple item adding.
|
|
@ -3,7 +3,7 @@ package com.pixelized.rplexicon.data.model
|
|||
import android.net.Uri
|
||||
import com.pixelized.rplexicon.data.model.roll.Throw
|
||||
import com.pixelized.rplexicon.script.Script
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache.attackIcon
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache.attackIcon
|
||||
|
||||
|
||||
data class Attack(
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.pixelized.rplexicon.data.model
|
|||
|
||||
import android.net.Uri
|
||||
import com.pixelized.rplexicon.data.model.roll.Throw
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache.objectIcon
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache.objectIcon
|
||||
|
||||
data class ObjectAction(
|
||||
val prefix: String?,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package com.pixelized.rplexicon.data.model
|
|||
import android.net.Uri
|
||||
import com.pixelized.rplexicon.data.model.roll.Throw
|
||||
import com.pixelized.rplexicon.script.Script
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache.skillIcon
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache.skillIcon
|
||||
|
||||
data class Skill(
|
||||
val name: String,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
package com.pixelized.rplexicon.data.model
|
||||
|
||||
import android.net.Uri
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache.spellIcon
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache.spellIcon
|
||||
|
||||
data class Spell(
|
||||
val name: String,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import com.pixelized.rplexicon.data.model.Property
|
|||
import com.pixelized.rplexicon.data.model.roll.Dice
|
||||
import com.pixelized.rplexicon.data.model.roll.Flat
|
||||
import com.pixelized.rplexicon.script.Script
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache.alterationIcon
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache.alterationIcon
|
||||
|
||||
data class Alteration(
|
||||
val name: String,
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import com.pixelized.rplexicon.data.model.item.InventoryPath
|
|||
import com.pixelized.rplexicon.data.model.item.Item
|
||||
import com.pixelized.rplexicon.data.network.ItemDto
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryItemUio
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache
|
||||
import javax.inject.Inject
|
||||
|
||||
class InventoryItemUioFactory @Inject constructor() {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ package com.pixelized.rplexicon.ui.screens.character.factory
|
|||
import android.content.Context
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.data.model.item.Item
|
||||
import com.pixelized.rplexicon.data.network.ItemDto
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item.ItemCategoryUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item.ItemUio
|
||||
import com.pixelized.rplexicon.utilitary.extentions.string.ImageCache
|
||||
import com.pixelized.rplexicon.utilitary.ImageCache
|
||||
import javax.inject.Inject
|
||||
|
||||
class ItemElementUioFactory @Inject constructor() {
|
||||
|
|
@ -13,6 +14,7 @@ class ItemElementUioFactory @Inject constructor() {
|
|||
fun toUio(
|
||||
context: Context,
|
||||
items: List<Item>,
|
||||
fire: List<ItemDto>,
|
||||
): List<ItemCategoryUio> {
|
||||
return items
|
||||
.groupBy { it.type }
|
||||
|
|
@ -21,14 +23,27 @@ class ItemElementUioFactory @Inject constructor() {
|
|||
title = group.key
|
||||
?: context.getString(R.string.character_sheet__item_list__uncategorized),
|
||||
items = group.value.map { item ->
|
||||
val fireItem = fire.find(id = item.id)
|
||||
ItemUio(
|
||||
id = item.id,
|
||||
name = item.fullName,
|
||||
context = item.context,
|
||||
icon = ImageCache.cache(uri = item.icon),
|
||||
enabled = (fireItem?.amount ?: 0) < 1,
|
||||
quantity = fireItem?.amount?.takeIf { it > 0 }?.let { "$it" },
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun List<ItemDto>.find(id: String): ItemDto? {
|
||||
return this.firstNotNullOfOrNull {
|
||||
if (it.id == id) {
|
||||
it
|
||||
} else {
|
||||
it.children.find(id = id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@ import androidx.compose.foundation.layout.Column
|
|||
import androidx.compose.foundation.layout.IntrinsicSize
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
|
|
@ -19,6 +18,13 @@ 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.DrawModifier
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.graphics.ColorFilter
|
||||
import androidx.compose.ui.graphics.ColorMatrix
|
||||
import androidx.compose.ui.graphics.Paint
|
||||
import androidx.compose.ui.graphics.drawscope.ContentDrawScope
|
||||
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
|
|
@ -26,6 +32,7 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
|
|||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.data.model.item.InventoryPath
|
||||
import com.pixelized.rplexicon.ui.composable.images.AsyncImage
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
|
||||
|
|
@ -35,6 +42,8 @@ data class ItemUio(
|
|||
val name: String,
|
||||
val context: String?,
|
||||
val icon: Any?,
|
||||
val enabled: Boolean,
|
||||
val quantity: String?,
|
||||
)
|
||||
|
||||
@Composable
|
||||
|
|
@ -46,7 +55,8 @@ fun Item(
|
|||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable(enabled = onClick != null) { onClick?.invoke() }
|
||||
.greyScale(enabled = item.enabled.not())
|
||||
.clickable(enabled = onClick != null && item.enabled) { onClick?.invoke() }
|
||||
.minimumInteractiveComponentSize()
|
||||
.height(intrinsicSize = IntrinsicSize.Min)
|
||||
.padding(paddingValues)
|
||||
|
|
@ -59,7 +69,7 @@ fun Item(
|
|||
model = item.icon,
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
modifier = Modifier.weight(weight = 1f),
|
||||
verticalArrangement = Arrangement.spacedBy(
|
||||
space = 4.dp,
|
||||
alignment = Alignment.CenterVertically
|
||||
|
|
@ -82,6 +92,13 @@ fun Item(
|
|||
)
|
||||
}
|
||||
}
|
||||
Text(
|
||||
style = MaterialTheme.typography.bodyMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
maxLines = 1,
|
||||
text = item.quantity?.let { "$it" } ?: "",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -98,6 +115,23 @@ private fun ItemPreview(
|
|||
}
|
||||
}
|
||||
|
||||
class GreyScaleModifier : DrawModifier {
|
||||
override fun ContentDrawScope.draw() {
|
||||
val saturationMatrix = ColorMatrix().apply { this.setToSaturation(0f) }
|
||||
val saturationFilter = ColorFilter.colorMatrix(saturationMatrix)
|
||||
val paint = Paint().apply {
|
||||
colorFilter = saturationFilter
|
||||
}
|
||||
drawIntoCanvas {
|
||||
it.saveLayer(Rect(0f, 0f, size.width, size.height), paint)
|
||||
drawContent()
|
||||
it.restore()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Modifier.greyScale(enabled: Boolean) = if (enabled) this.then(GreyScaleModifier()) else this
|
||||
|
||||
private class ItemProvider : PreviewParameterProvider<ItemUio> {
|
||||
override val values: Sequence<ItemUio> = sequenceOf(
|
||||
ItemUio(
|
||||
|
|
@ -105,12 +139,16 @@ private class ItemProvider : PreviewParameterProvider<ItemUio> {
|
|||
name = "Bourse",
|
||||
context = "Un petite bourse.",
|
||||
icon = R.drawable.icbg_pouch_a_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
ItemUio(
|
||||
id = "2ecf41c2-06b1-4f2d-a6d9-b6adcaf05aba",
|
||||
name = "Sac à dos",
|
||||
context = null,
|
||||
icon = R.drawable.icbg_backpack_b_unfaded,
|
||||
enabled = false,
|
||||
quantity = "1",
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
@ -294,24 +294,32 @@ private fun ItemLisPreview() {
|
|||
name = "Bourse",
|
||||
context = "Une petite bourse en cuir.",
|
||||
icon = R.drawable.icbg_leather_pouch_a_unfaded,
|
||||
enabled = false,
|
||||
quantity = "1",
|
||||
),
|
||||
ItemUio(
|
||||
id = "7d27561b-f2f4-4899-a2fc-df3501b1b66b",
|
||||
name = "Bourse",
|
||||
context = "Une petite bourse.",
|
||||
icon = R.drawable.icbg_pouch_a_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
ItemUio(
|
||||
id = "2ecf41c2-06b1-4f2d-a6d9-b6adcaf05aba",
|
||||
name = "Sac à dos",
|
||||
context = "Sac à dos pour aventurier.",
|
||||
icon = R.drawable.icbg_backpack_a_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
ItemUio(
|
||||
id = "43424bbc-0117-44f8-b512-6d469a05e6c2",
|
||||
name = "Sac à dos",
|
||||
context = "Sac à dos pour aventurier.",
|
||||
icon = R.drawable.icbg_backpack_b_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
|
@ -323,12 +331,16 @@ private fun ItemLisPreview() {
|
|||
name = "Parchemin d'Arme spirituelle",
|
||||
context = null,
|
||||
icon = R.drawable.icbg_book_signedtradebisa_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
ItemUio(
|
||||
id = "eda09856-5a91-4411-ac75-248a16ce1060",
|
||||
name = "Parchemin de Bénédiction",
|
||||
context = null,
|
||||
icon = R.drawable.icbg_scroll_of_bless_unfaded,
|
||||
enabled = true,
|
||||
quantity = null,
|
||||
),
|
||||
)
|
||||
),
|
||||
|
|
|
|||
|
|
@ -7,23 +7,29 @@ import androidx.compose.runtime.State
|
|||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.rplexicon.data.model.item.Item
|
||||
import com.pixelized.rplexicon.data.model.item.InventoryPath
|
||||
import com.pixelized.rplexicon.data.model.item.InventoryPath.Companion.ROOT
|
||||
import com.pixelized.rplexicon.data.repository.character.ItemsRepository
|
||||
import com.pixelized.rplexicon.data.repository.firebase.InventoryFireRepository
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument
|
||||
import com.pixelized.rplexicon.ui.screens.character.factory.ItemElementUioFactory
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class ItemListViewModel @Inject constructor(
|
||||
private val itemsRepository: ItemsRepository,
|
||||
private val fireRepository: InventoryFireRepository,
|
||||
private val factory: ItemElementUioFactory,
|
||||
savedStateHandle: SavedStateHandle,
|
||||
) : ViewModel() {
|
||||
private val character = savedStateHandle.characterSheetArgument.name
|
||||
|
||||
private val filter = MutableStateFlow("")
|
||||
|
||||
|
|
@ -43,21 +49,23 @@ class ItemListViewModel @Inject constructor(
|
|||
@Stable
|
||||
get() {
|
||||
val context = LocalContext.current
|
||||
return itemsRepository.data.combine(filter) { items, filter -> items to filter }
|
||||
.map { (items: Map<String, Item>, filter: String) ->
|
||||
items.values
|
||||
.filter {
|
||||
val name = it.fullName.contains(other = filter, ignoreCase = true)
|
||||
val type = it.type?.contains(other = filter, ignoreCase = true) == true
|
||||
name || type
|
||||
}
|
||||
.sortedWith(compareBy(Collator.getInstance()) { it.fullName })
|
||||
.sortedBy { it.type }
|
||||
}
|
||||
.map { items: List<Item> ->
|
||||
factory.toUio(context = context, items = items)
|
||||
}
|
||||
.collectAsState(initial = emptyList())
|
||||
return combine(
|
||||
filter,
|
||||
itemsRepository.data,
|
||||
fireRepository.getInventory(character = character, path = ROOT),
|
||||
) { filter, items, fires ->
|
||||
val filteredItems = items.values
|
||||
.filter {
|
||||
val name = it.fullName.contains(other = filter, ignoreCase = true)
|
||||
val type = it.type?.contains(other = filter, ignoreCase = true) == true
|
||||
name || type
|
||||
}
|
||||
.sortedWith(compareBy(Collator.getInstance()) { it.fullName })
|
||||
.sortedBy { it.type }
|
||||
factory.toUio(context = context, items = filteredItems, fire = fires)
|
||||
}.collectAsState(
|
||||
initial = emptyList()
|
||||
)
|
||||
}
|
||||
|
||||
fun updateItemList() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.rplexicon.utilitary.extentions.string
|
||||
package com.pixelized.rplexicon.utilitary
|
||||
|
||||
import android.net.Uri
|
||||
import android.util.Log
|
||||
|
|
@ -90,6 +90,7 @@ object ImageCache {
|
|||
"https://drive.google.com/uc?export=view&id=1AeSHg792EwVbkjCNjJaqzC4v0uNj9NRn" to R.drawable.ic_drive_fire_starter,
|
||||
"https://drive.google.com/uc?export=view&id=1Dc0hBGXTNP8dnYqHJlSsK1WgWAsWtCV9" to R.drawable.ic_drive_lantern_of_revealing,
|
||||
"https://drive.google.com/uc?export=view&id=1KPlgQK1C3lfZn3ZHTHd-dqiSINjQpnH9" to R.drawable.ic_drive_ring_of_kazan,
|
||||
"https://drive.google.com/uc?export=view&id=1YYgZ2SlSn6TkRiphpIf62KgwTZWQZHQJ" to R.drawable.ic_drive_tome_of_strahd,
|
||||
)
|
||||
|
||||
private val alterations = hashMapOf(
|
||||
|
|
@ -358,7 +359,7 @@ object ImageCache {
|
|||
|
||||
fun cache(uri: Uri?): Any = when (uri) {
|
||||
null -> R.drawable.icbg_generic_darkness_icon
|
||||
else -> this.uri[uri.toString()] ?: kotlin.run {
|
||||
else -> ImageCache.uri[uri.toString()] ?: kotlin.run {
|
||||
Log.v("ImageCache", "$uri")
|
||||
uri
|
||||
}
|
||||
|
Before Width: | Height: | Size: 49 KiB |
BIN
app/src/main/res/drawable/ic_copper_coin_pile_unfaded.webp
Normal file
|
After Width: | Height: | Size: 9.5 KiB |
BIN
app/src/main/res/drawable/ic_drive_tome_of_strahd.webp
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 39 KiB |
BIN
app/src/main/res/drawable/ic_electrum_coin_pile_unfaded.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 44 KiB |
BIN
app/src/main/res/drawable/ic_gold_coin_pile_unfaded.webp
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 39 KiB |
BIN
app/src/main/res/drawable/ic_silver_coin_pile_unfaded.webp
Normal file
|
After Width: | Height: | Size: 9.2 KiB |