diff --git a/app/src/main/java/com/pixelized/rplexicon/model/Inventory.kt b/app/src/main/java/com/pixelized/rplexicon/model/Inventory.kt index aa6bff2..5a7971f 100644 --- a/app/src/main/java/com/pixelized/rplexicon/model/Inventory.kt +++ b/app/src/main/java/com/pixelized/rplexicon/model/Inventory.kt @@ -11,7 +11,7 @@ data class Inventory( ) fun find(container: String): Item.Builder? { - return items.firstOrNull { it.find(name = container) != null } + return items.localFind { it.find(name = container) } } } @@ -34,9 +34,20 @@ data class Inventory( fun find(name: String): Builder? { return when (this.name) { name -> this - else -> items.firstOrNull { it.find(name = name) != null } + else -> items.localFind { it.find(name = name) } } } } } +} + +private inline fun Iterable.localFind(predicate: (T) -> T?): T? { + var single: T? = null + for (element in this) { + single = predicate(element) + if (single != null) { + break + } + } + return single } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt index fde25f1..a556422 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/CharacterSheetScreen.kt @@ -56,6 +56,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp +import androidx.compose.ui.zIndex import androidx.hilt.navigation.compose.hiltViewModel import com.pixelized.rplexicon.LocalRollOverlay import com.pixelized.rplexicon.LocalSnack @@ -81,6 +82,7 @@ import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.Proficienc import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPreview import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyViewModel import com.pixelized.rplexicon.ui.theme.LexiconTheme +import com.pixelized.rplexicon.utilitary.extentions.lexiconShadow import kotlinx.coroutines.launch @OptIn( @@ -226,7 +228,6 @@ private fun CharacterSheetContent( contentWindowInsets = NO_WINDOW_INSETS, topBar = { TopAppBar( - modifier = Modifier.shadow(elevation = 4.dp), navigationIcon = { IconButton(onClick = onBack) { Icon( @@ -278,6 +279,9 @@ private fun CharacterSheetContent( ) { Column { PagerHeader( + modifier = Modifier + .zIndex(1f) + .lexiconShadow(), pagerState = pagerState, onTab = onTab, ) @@ -310,12 +314,15 @@ private fun CharacterSheetContent( @OptIn(ExperimentalFoundationApi::class) @Composable private fun PagerHeader( + modifier: Modifier = Modifier, pagerState: PagerState, tabs: List = headers(), onTab: (Int) -> Unit, ) { ScrollableTabRow( + modifier = modifier, selectedTabIndex = pagerState.currentPage, + divider = { }, ) { tabs.forEachIndexed { index, tab -> Tab( @@ -364,7 +371,7 @@ private fun CharacterScreenPreview( CharacterSheetContent( modifier = Modifier.fillMaxSize(), sheetState = sheetState, - pagerState = rememberPagerState(initialPage = preview) { 2 }, + pagerState = rememberPagerState(initialPage = preview) { 4 }, refreshState = rememberPullRefreshState(refreshing = false, onRefresh = { }), name = "Brulkhai", onBack = { }, diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/actions/InventoryItem.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/actions/InventoryItem.kt index 77a7540..915cc53 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/actions/InventoryItem.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/actions/InventoryItem.kt @@ -2,28 +2,37 @@ package com.pixelized.rplexicon.ui.screens.character.composable.actions import android.content.res.Configuration.UI_MODE_NIGHT_NO import android.content.res.Configuration.UI_MODE_NIGHT_YES -import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ExperimentalLayoutApi import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.IntrinsicSize import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.material3.Divider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.tooling.preview.Preview -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.unit.dp +import com.pixelized.rplexicon.ui.screens.character.composable.preview.rememberInventoryListState import com.pixelized.rplexicon.ui.theme.LexiconTheme +import com.pixelized.rplexicon.utilitary.rememberTextSize @Stable data class InventoryItemUio( val name: String, val amount: String? = null, + val items: List = emptyList(), ) @OptIn(ExperimentalLayoutApi::class) @@ -33,30 +42,63 @@ fun InventoryItem( padding: PaddingValues = PaddingValues(horizontal = 16.dp, vertical = 2.dp), item: InventoryItemUio, ) { - FlowRow( + Column( modifier = Modifier .padding(paddingValues = padding) .then(other = modifier), ) { - Text( - modifier = Modifier.alignByBaseline(), - fontWeight = FontWeight.Bold, - style = MaterialTheme.typography.bodyMedium, - text = item.name, - ) - item.amount?.let { + FlowRow { Text( modifier = Modifier.alignByBaseline(), - fontWeight = FontWeight.Medium, - style = MaterialTheme.typography.labelLarge, - text = " : ", - ) - Text( - modifier = Modifier.alignByBaseline(), - fontWeight = FontWeight.Light, + fontWeight = FontWeight.Bold, style = MaterialTheme.typography.bodyMedium, - text = it + text = item.name, ) + item.amount?.let { + Text( + modifier = Modifier.alignByBaseline(), + fontWeight = FontWeight.Medium, + style = MaterialTheme.typography.labelLarge, + text = " : ", + ) + Text( + modifier = Modifier.alignByBaseline(), + fontWeight = FontWeight.Light, + style = MaterialTheme.typography.bodyMedium, + text = it + ) + } + } + val lastIndex = remember(item.items.size) { item.items.lastIndex } + item.items.forEachIndexed { index, item -> + Row( + modifier = Modifier.height(intrinsicSize = IntrinsicSize.Min), + ) { + val size = rememberTextSize(style = MaterialTheme.typography.bodyMedium) + if (index == lastIndex) { + Divider( + modifier = Modifier + .height(height = 3.dp + size.height / 2) + .width(1.dp) + ) + } else { + Divider( + modifier = Modifier + .fillMaxHeight() + .width(1.dp) + ) + } + Divider( + modifier = Modifier + .padding(top = 2.dp + size.height / 2) + .height(1.dp) + .width(8.dp) + ) + InventoryItem( + padding = PaddingValues(start = 7.dp, top = 2.dp, bottom = 2.dp), + item = item, + ) + } } } } @@ -64,25 +106,17 @@ fun InventoryItem( @Composable @Preview(uiMode = UI_MODE_NIGHT_NO) @Preview(uiMode = UI_MODE_NIGHT_YES) -private fun InventoryItemPreview( - @PreviewParameter(InventoryItemPreviewProvider::class) preview: InventoryItemUio, -) { +private fun InventoryItemPreview() { LexiconTheme { Surface { - InventoryItem(item = preview) + Column { + val items = rememberInventoryListState() + items.value.forEach { + InventoryItem( + item = it, + ) + } + } } } -} - -private class InventoryItemPreviewProvider : PreviewParameterProvider { - override val values: Sequence = sequenceOf( - InventoryItemUio( - name = "- Cordes", - amount = "15 mètres", - ), - InventoryItemUio( - name = "- Piège de chasse", - amount = null, - ) - ) } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt index 4ab0ced..74b0bfc 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/composable/preview/rememberInventoryListState.kt @@ -5,8 +5,6 @@ import androidx.compose.runtime.Stable import androidx.compose.runtime.State import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import com.pixelized.rplexicon.R -import com.pixelized.rplexicon.ui.screens.character.composable.actions.EquipmentItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio @Composable @@ -15,18 +13,26 @@ fun rememberInventoryListState(): State> { return remember { mutableStateOf( listOf( - InventoryItemUio(name = "Bourse"), - InventoryItemUio(name = "- Or", amount = "21"), - InventoryItemUio(name = "Sac à dos"), - InventoryItemUio(name = "- Sac de couchage"), - InventoryItemUio(name = "- Kit de cuisine"), - InventoryItemUio(name = "- Boite d'allume-feu"), - InventoryItemUio(name = "- Torches", amount = "10"), - InventoryItemUio(name = "- Rations journalières", amount = "10"), - InventoryItemUio(name = "- Outre d'eau"), - InventoryItemUio(name = "- Cordes", amount = "15 mètres"), - InventoryItemUio(name = "- Piège de chasse"), - InventoryItemUio(name = "- Bâton de marche"), + InventoryItemUio( + name = "Bourse", + items = listOf( + InventoryItemUio(name = "Or", amount = "21"), + ), + ), + InventoryItemUio( + name = "Sac à dos", + items = listOf( + InventoryItemUio(name = "Sac de couchage"), + InventoryItemUio(name = "Kit de cuisine"), + InventoryItemUio(name = "Boite d'allume-feu"), + InventoryItemUio(name = "Torches", amount = "10"), + InventoryItemUio(name = "Rations journalières", amount = "10"), + InventoryItemUio(name = "Outre d'eau"), + InventoryItemUio(name = "Cordes", amount = "15 mètres"), + InventoryItemUio(name = "Piège de chasse"), + InventoryItemUio(name = "Bâton de marche"), + ), + ), InventoryItemUio(name = "Dague"), InventoryItemUio(name = "Javelot", amount = "4"), InventoryItemUio(name = "Cape de protection"), diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/ItemUioFactory.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/ItemUioFactory.kt new file mode 100644 index 0000000..b69dc02 --- /dev/null +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/factory/ItemUioFactory.kt @@ -0,0 +1,16 @@ +package com.pixelized.rplexicon.ui.screens.character.factory + +import com.pixelized.rplexicon.model.Inventory +import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio +import javax.inject.Inject + +class ItemUioFactory @Inject constructor() { + + fun toUio(item: Inventory.Item): InventoryItemUio { + return InventoryItemUio( + name = item.name, + amount = item.amount, + items = item.items.map { toUio(it) } + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt index f8a35d1..d5d784b 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryPage.kt @@ -5,6 +5,7 @@ import android.content.res.Configuration.UI_MODE_NIGHT_YES import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.items @@ -94,12 +95,6 @@ private fun InventoryPageContent( } items(items = inventory.value) { InventoryItem( - modifier = Modifier.padding( - top = when (it.name.contains("-")) { - true -> 0.dp - else -> 4.dp - } - ), item = it, ) } diff --git a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryViewModel.kt b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryViewModel.kt index af91176..4576a30 100644 --- a/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryViewModel.kt +++ b/app/src/main/java/com/pixelized/rplexicon/ui/screens/character/pages/inventory/InventoryViewModel.kt @@ -13,6 +13,7 @@ import com.pixelized.rplexicon.repository.data.character.InventoryRepository import com.pixelized.rplexicon.ui.navigation.screens.characterSheetArgument import com.pixelized.rplexicon.ui.screens.character.composable.actions.EquipmentItemUio import com.pixelized.rplexicon.ui.screens.character.composable.actions.InventoryItemUio +import com.pixelized.rplexicon.ui.screens.character.factory.ItemUioFactory import com.pixelized.rplexicon.ui.screens.character.pages.actions.SkillDetailUio import com.pixelized.rplexicon.utilitary.extentions.context import dagger.hilt.android.lifecycle.HiltViewModel @@ -28,6 +29,7 @@ class InventoryViewModel @Inject constructor( private val inventoryRepository: InventoryRepository, private val equipmentRepository: EquipmentRepository, private val descriptionRepository: DescriptionRepository, + private val itemFactory: ItemUioFactory, savedStateHandle: SavedStateHandle, application: Application ) : AndroidViewModel(application) { @@ -48,15 +50,10 @@ class InventoryViewModel @Inject constructor( init { viewModelScope.launch { launch(Dispatchers.IO) { - inventoryRepository.data.collect { - val items = it[character]?.items?.map { item -> - InventoryItemUio( - name = item.name, - amount = item.amount, - ) - } ?: emptyList() + inventoryRepository.data.collect { inventories -> + val items = inventories[character]?.items?.map { itemFactory.toUio(it) } withContext(Dispatchers.Main) { - _inventory.value = items + _inventory.value = items ?: emptyList() } } } @@ -88,7 +85,7 @@ class InventoryViewModel @Inject constructor( } } } - + fun showSkillDetailDialog(item: String) { val description = descriptionRepository.find(name = item) diff --git a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt index 7a9e637..40e0c3a 100644 --- a/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt +++ b/app/src/main/java/com/pixelized/rplexicon/utilitary/extentions/ModifierEx.kt @@ -2,14 +2,11 @@ package com.pixelized.rplexicon.utilitary.extentions import androidx.compose.animation.core.FiniteAnimationSpec import androidx.compose.animation.core.Transition -import androidx.compose.animation.core.animateFloatAsState -import androidx.compose.animation.core.animateOffsetAsState import androidx.compose.animation.core.spring import androidx.compose.foundation.ScrollState import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.clickable -import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.detectTransformGestures import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.isSystemInDarkTheme @@ -18,6 +15,7 @@ import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.DividerDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.runtime.Composable @@ -31,6 +29,9 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.composed import androidx.compose.ui.draw.clip +import androidx.compose.ui.draw.drawBehind +import androidx.compose.ui.draw.drawWithContent +import androidx.compose.ui.draw.shadow import androidx.compose.ui.geometry.Offset import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Shape @@ -151,4 +152,23 @@ fun Modifier.ddBorder( .clip( shape = inner, ) +} + +fun Modifier.lexiconShadow() = composed { + if (isSystemInDarkTheme()) { + val color = DividerDefaults.color + drawWithContent { + drawContent() + val thickness = DividerDefaults.Thickness.toPx() + val y = size.height + drawLine( + color = color, + start = Offset(0f, y), + end = Offset(size.width, y), + strokeWidth = thickness + ) + } + } else { + shadow(elevation = 4.dp) + } } \ No newline at end of file