Skip to content

Commit

Permalink
Merge pull request #367 from fmasa/qualities
Browse files Browse the repository at this point in the history
Trapping Qualities and Weapon Groups Journal
  • Loading branch information
fmasa authored Nov 18, 2024
2 parents d1ecf0c + 48ed2d7 commit c9ed187
Show file tree
Hide file tree
Showing 34 changed files with 875 additions and 290 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import cz.frantisekmasa.wfrp_master.common.compendium.journal.Journal
import cz.frantisekmasa.wfrp_master.common.compendium.journal.JournalScreenModel
import cz.frantisekmasa.wfrp_master.common.compendium.journal.rules.ConditionsJournalProvider
import cz.frantisekmasa.wfrp_master.common.compendium.journal.rules.DiseaseSymptomProvider
import cz.frantisekmasa.wfrp_master.common.compendium.journal.rules.TrappingJournalProvider
import cz.frantisekmasa.wfrp_master.common.compendium.miracle.MiracleCompendiumScreenModel
import cz.frantisekmasa.wfrp_master.common.compendium.skill.SkillCompendiumScreenModel
import cz.frantisekmasa.wfrp_master.common.compendium.spell.SpellCompendiumScreenModel
Expand Down Expand Up @@ -170,6 +171,7 @@ val appModule =
bindSingleton<Journal> { FirestoreJournal(instance()) }
bindSingleton { ConditionsJournalProvider(instance()) }
bindSingleton { DiseaseSymptomProvider(instance(), instance(), instance()) }
bindSingleton { TrappingJournalProvider(instance(), instance(), instance()) }

bindSingleton<Compendium<Disease>> {
FirestoreCompendium(Schema.Compendium.DISEASES, instance(), serializer())
Expand Down Expand Up @@ -206,6 +208,7 @@ val appModule =
instance(),
instance(),
instance(),
instance(),
)
}

Expand Down Expand Up @@ -361,7 +364,7 @@ val appModule =
TraitCompendiumScreenModel(partyId, instance(), instance(), instance(), instance(), instance())
}
bindFactory { partyId: PartyId ->
TrappingCompendiumScreenModel(partyId, instance(), instance(), instance(), instance())
TrappingCompendiumScreenModel(partyId, instance(), instance(), instance(), instance(), instance())
}
bindFactory { partyId: PartyId ->
DiseaseCompendiumScreenModel(partyId, instance(), instance(), instance(), instance(), instance())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,5 @@ fun <Q : Quality, F : Flaw> TrappingFeatureList(
@Composable
@Stable
fun <T : TrappingFeature> translateFeatures(features: Map<T, Rating>): List<String> {
return features.map { (feature, rating) ->
val name = feature.localizedName

if (!feature.hasRating) {
return@map name
}

val ratingUnit = feature.ratingUnit
val formattedRating = if (ratingUnit != null) "($rating$ratingUnit)" else rating.toString()

"$name $formattedRating"
}
return features.map { (feature, rating) -> feature.formatValue(rating) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ class CharacterDiseaseDetailScreen(characterId: CharacterId, private val disease
symptoms = state.symptoms,
permanentEffects = disease.permanentEffects,
description = disease.description,
partyId = characterId.partyId,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,45 +1,36 @@
package cz.frantisekmasa.wfrp_master.common.character.diseases

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.ExperimentalLayoutApi
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Chip
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.key
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import com.benasher44.uuid.Uuid
import com.halilibo.richtext.commonmark.Markdown
import com.halilibo.richtext.ui.material.RichText
import cz.frantisekmasa.wfrp_master.common.Str
import cz.frantisekmasa.wfrp_master.common.compendium.journal.JournalEntryScreen
import cz.frantisekmasa.wfrp_master.common.core.domain.party.PartyId
import cz.frantisekmasa.wfrp_master.common.core.logging.Reporting
import cz.frantisekmasa.wfrp_master.common.core.ui.navigation.LocalNavigationTransaction
import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.Spacing
import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.LocalPersistentSnackbarHolder
import cz.frantisekmasa.wfrp_master.common.core.ui.text.JournalItem
import cz.frantisekmasa.wfrp_master.common.core.ui.text.JournalItemList
import cz.frantisekmasa.wfrp_master.common.core.ui.text.SingleLineTextValue
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.collections.immutable.ImmutableList

@Composable
fun DiseaseDetailBody(
subheadBar: @Composable ColumnScope.() -> Unit = {},
partyId: PartyId,
symptoms: ImmutableList<Symptom>,
permanentEffects: String,
description: String,
) {
Column(Modifier.padding(Spacing.bodyPadding)) {
subheadBar()

SymptomList(
partyId = partyId,
symptoms = symptoms,
JournalItemList(
label = stringResource(Str.diseases_label_symptoms),
itemType = "disease_symptom",
items = symptoms,
)

SingleLineTextValue(
Expand All @@ -54,48 +45,15 @@ fun DiseaseDetailBody(
}

data class Symptom(
val name: String,
val journalEntryId: Uuid?,
val journalEntryName: String,
)

@Composable
private fun SymptomList(
partyId: PartyId,
symptoms: ImmutableList<Symptom>,
) {
if (symptoms.isEmpty()) return

Column {
Text(
"${stringResource(Str.diseases_label_symptoms)}:",
fontWeight = FontWeight.Bold,
modifier = Modifier.padding(end = Spacing.tiny),
)
@OptIn(ExperimentalLayoutApi::class)
FlowRow(
horizontalArrangement = Arrangement.spacedBy(Spacing.tiny),
) {
val navigation = LocalNavigationTransaction.current
val snackbarHolder = LocalPersistentSnackbarHolder.current

symptoms.forEach { symptom ->
key(symptom.name) {
val notFoundMessage = stringResource(Str.journal_messages_entry_not_found, symptom.journalEntryName)
Chip(
onClick = {
if (symptom.journalEntryId != null) {
Reporting.record { journalOpened("disease_symptom") }
navigation.navigate(JournalEntryScreen(partyId, symptom.journalEntryId))
} else {
snackbarHolder.showSnackbar(notFoundMessage)
}
},
) {
Text(symptom.name)
}
}
}
}
private val name: String,
override val journalEntryId: Uuid?,
override val journalEntryName: String,
override val partyId: PartyId,
) : JournalItem {
override val key = name

@Composable
override fun getName(): String {
return name
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Edit
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
Expand All @@ -25,6 +26,7 @@ import cz.frantisekmasa.wfrp_master.common.character.trappings.detail.QuantityBa
import cz.frantisekmasa.wfrp_master.common.character.trappings.detail.RangedWeaponDetailBody
import cz.frantisekmasa.wfrp_master.common.character.trappings.detail.SimpleTrappingDetailBody
import cz.frantisekmasa.wfrp_master.common.character.trappings.detail.WornBar
import cz.frantisekmasa.wfrp_master.common.compendium.journal.rules.TrappingJournal
import cz.frantisekmasa.wfrp_master.common.compendium.trapping.CompendiumTrappingDetailScreen
import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId
import cz.frantisekmasa.wfrp_master.common.core.domain.localizedName
Expand All @@ -44,7 +46,7 @@ import dev.icerock.moko.resources.compose.stringResource

class CharacterTrappingDetailScreen(
characterId: CharacterId,
itemId: InventoryItemId,
private val itemId: InventoryItemId,
) : CharacterItemDetailScreen(characterId, itemId) {
override val key =
"parties/${characterId.partyId}/characters/${characterId.id}/trappings/$itemId"
Expand All @@ -53,8 +55,12 @@ class CharacterTrappingDetailScreen(
override fun Content() {
val screenModel: CharacterTrappingsDetailScreenModel = rememberScreenModel(arg = characterId)

Detail(screenModel) { trapping, isGameMaster ->
Detail(
remember { screenModel.getTrappingDetail(itemId) },
isGameMasterFlow = screenModel.isGameMaster,
) { state, isGameMaster ->
val (dialogOpened, setDialogOpened) = rememberSaveable { mutableStateOf(false) }
val trapping = state.trapping

if (dialogOpened) {
EditTrappingDialog(
Expand All @@ -74,6 +80,7 @@ class CharacterTrappingDetailScreen(
onOpenDetailRequest = {
navigation.navigate(CharacterTrappingDetailScreen(characterId, it.id))
},
trappingJournal = state.trappingJournal,
)
}
}
Expand All @@ -83,6 +90,7 @@ class CharacterTrappingDetailScreen(
private fun TrappingDetail(
characterId: CharacterId,
trapping: InventoryItem,
trappingJournal: TrappingJournal,
screenModel: CharacterTrappingsDetailScreenModel,
isGameMaster: Boolean,
onEditRequest: () -> Unit,
Expand Down Expand Up @@ -169,6 +177,7 @@ private fun TrappingDetail(
flaws = type.flaws,
encumbrance = trapping.encumbrance,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.Armour -> {
Expand All @@ -181,6 +190,7 @@ private fun TrappingDetail(
encumbrance = trapping.encumbrance,
description = trapping.description,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.SimpleTrapping -> {
Expand All @@ -190,6 +200,7 @@ private fun TrappingDetail(
encumbrance = trapping.encumbrance,
description = trapping.description,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
null -> {
Expand All @@ -199,6 +210,7 @@ private fun TrappingDetail(
encumbrance = trapping.encumbrance,
description = trapping.description,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.Container -> {
Expand All @@ -215,6 +227,7 @@ private fun TrappingDetail(
onAddToContainerRequest = {
screenModel.addToContainer(trapping = it, container = trapping)
},
trappingJournal = trappingJournal,
)
}
is TrappingType.ClothingOrAccessory -> {
Expand All @@ -224,6 +237,7 @@ private fun TrappingDetail(
encumbrance = trapping.encumbrance,
description = trapping.description,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.MeleeWeapon -> {
Expand All @@ -238,6 +252,7 @@ private fun TrappingDetail(
description = trapping.description,
encumbrance = trapping.encumbrance,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.Prosthetic -> {
Expand All @@ -247,6 +262,7 @@ private fun TrappingDetail(
encumbrance = trapping.encumbrance,
description = trapping.description,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
is TrappingType.RangedWeapon -> {
Expand All @@ -261,8 +277,14 @@ private fun TrappingDetail(
description = trapping.description,
encumbrance = trapping.encumbrance,
characterTrapping = trapping,
trappingJournal = trappingJournal,
)
}
}
}
}

data class CharacterTrappingDetailScreenState(
val trapping: InventoryItem,
val trappingJournal: TrappingJournal,
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package cz.frantisekmasa.wfrp_master.common.character.trappings

import com.benasher44.uuid.Uuid
import cz.frantisekmasa.wfrp_master.common.compendium.journal.rules.TrappingJournalProvider
import cz.frantisekmasa.wfrp_master.common.core.CharacterItemScreenModel
import cz.frantisekmasa.wfrp_master.common.core.auth.UserProvider
import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterRepository
Expand All @@ -11,6 +13,7 @@ import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.TrappingType
import cz.frantisekmasa.wfrp_master.common.core.logging.Reporting
import cz.frantisekmasa.wfrp_master.common.core.utils.right
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map

Expand All @@ -21,6 +24,7 @@ class CharacterTrappingsDetailScreenModel(
private val inventoryItems: InventoryItemRepository,
characters: CharacterRepository,
private val trappingSaver: TrappingSaver,
private val trappingJournalProvider: TrappingJournalProvider,
) : CharacterItemScreenModel<InventoryItem>(
characterId,
inventoryItems,
Expand Down Expand Up @@ -68,6 +72,12 @@ class CharacterTrappingsDetailScreenModel(
inventoryItems.save(characterId, trapping.copy(containerId = null))
}

fun getTrappingDetail(trappingId: Uuid) =
getItem(trappingId)
.combine(trappingJournalProvider.getTrappingJournal(characterId.partyId)) { trappingOrError, trappingJournal ->
trappingOrError.map { CharacterTrappingDetailScreenState(it, trappingJournal) }
}

/**
* Returns true when trapping was added to container and false otherwise
*/
Expand Down
Loading

0 comments on commit c9ed187

Please sign in to comment.