diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/DependencyInjection.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/DependencyInjection.kt index 384fe01b8..e305e20d0 100644 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/DependencyInjection.kt +++ b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/DependencyInjection.kt @@ -22,11 +22,9 @@ import cz.frantisekmasa.wfrp_master.common.core.PartyScreenModel import cz.frantisekmasa.wfrp_master.common.core.cache.CharacterRepositoryIdentityMap import cz.frantisekmasa.wfrp_master.common.core.cache.PartyRepositoryIdentityMap import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterAvatarChanger -import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterFeatureRepository import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterItem import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterItemRepository import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterRepository -import cz.frantisekmasa.wfrp_master.common.core.domain.character.Feature import cz.frantisekmasa.wfrp_master.common.core.domain.compendium.Compendium import cz.frantisekmasa.wfrp_master.common.core.domain.compendium.FirestoreCompendium import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId @@ -38,11 +36,9 @@ import cz.frantisekmasa.wfrp_master.common.core.domain.religion.MiracleRepositor import cz.frantisekmasa.wfrp_master.common.core.domain.skills.SkillRepository import cz.frantisekmasa.wfrp_master.common.core.domain.spells.SpellRepository import cz.frantisekmasa.wfrp_master.common.core.domain.talents.TalentRepository -import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.Armour import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.InventoryItemRepository import cz.frantisekmasa.wfrp_master.common.core.firebase.Schema import cz.frantisekmasa.wfrp_master.common.core.firebase.functions.CloudFunctionCharacterAvatarChanger -import cz.frantisekmasa.wfrp_master.common.core.firebase.repositories.FirestoreCharacterFeatureRepository import cz.frantisekmasa.wfrp_master.common.core.firebase.repositories.FirestoreCharacterItemRepository import cz.frantisekmasa.wfrp_master.common.core.firebase.repositories.FirestoreCharacterRepository import cz.frantisekmasa.wfrp_master.common.core.firebase.repositories.FirestoreEncounterRepository @@ -76,7 +72,6 @@ import kotlin.random.Random import cz.frantisekmasa.wfrp_master.common.core.firebase.serializationAggregateMapper as mapper - val appModule = DI.Module("Common") { import(platformModule) @@ -131,17 +126,8 @@ val appModule = DI.Module("Common") { bindSingleton { CloudFunctionCharacterAvatarChanger(instance()) } - bindSingleton> { - FirestoreCharacterFeatureRepository( - Feature.ARMOR, - instance(), - Armour(), - mapper(), - ) - } - bindFactory { characterId: CharacterId -> - TrappingsScreenModel(characterId, instance(), instance(), instance()) + TrappingsScreenModel(characterId, instance(), instance()) } /** @@ -149,7 +135,7 @@ val appModule = DI.Module("Common") { */ bindFactory { characterId: CharacterId -> - CharacterCombatScreenModel(characterId, instance(), instance(), instance()) + CharacterCombatScreenModel(characterId, instance(), instance()) } bindFactory { characterId: CharacterId -> CharacteristicsScreenModel(characterId, instance()) } bindFactory { characterId: CharacterId -> diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/combat/CharacterCombatScreenModel.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/combat/CharacterCombatScreenModel.kt index 67bfc2342..33b628c45 100644 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/combat/CharacterCombatScreenModel.kt +++ b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/combat/CharacterCombatScreenModel.kt @@ -4,7 +4,6 @@ import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.ScreenModel import cz.frantisekmasa.wfrp_master.common.core.domain.Damage import cz.frantisekmasa.wfrp_master.common.core.domain.HitLocation -import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterFeatureRepository import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterRepository import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.Armour @@ -22,7 +21,6 @@ class CharacterCombatScreenModel( characterId: CharacterId, trappingRepository: InventoryItemRepository, characterRepository: CharacterRepository, - armorRepository: CharacterFeatureRepository, ) : ScreenModel { private val trappingsFlow = trappingRepository.findAllForCharacter(characterId) private val characterFlow = characterRepository.getLive(characterId) @@ -50,13 +48,7 @@ class CharacterCombatScreenModel( .toList() } - private val legacyArmourFlow = armorRepository - .getLive(characterId) - .right() - - val armour: Flow = legacyArmourFlow.combine(trappingsFlow) { armour, items -> - armour + Armour.fromItems(items) - } + val armour: Flow = trappingsFlow.map { items -> Armour.fromItems(items) } val armourPieces: Flow>> = trappingsFlow.map { trappings -> val locations = mutableMapOf>() diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/ArmourCard.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/ArmourCard.kt deleted file mode 100644 index 3aa43e6c6..000000000 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/ArmourCard.kt +++ /dev/null @@ -1,169 +0,0 @@ -package cz.frantisekmasa.wfrp_master.common.character.trappings - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.material.ContentAlpha -import androidx.compose.material.Icon -import androidx.compose.material.LocalContentAlpha -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.Armour -import cz.frantisekmasa.wfrp_master.common.core.shared.Resources -import cz.frantisekmasa.wfrp_master.common.core.shared.drawableResource -import cz.frantisekmasa.wfrp_master.common.core.ui.cards.CardContainer -import cz.frantisekmasa.wfrp_master.common.core.ui.cards.CardTitle -import cz.frantisekmasa.wfrp_master.common.core.ui.forms.NumberPicker -import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.UserTip -import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.UserTipCard -import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.VisualOnlyIconDescription -import cz.frantisekmasa.wfrp_master.common.localization.LocalStrings - - -@Composable -internal fun ArmourCard(armour: TrappingsScreenModel.EquippedArmour, onChange: (Armour) -> Unit) { - val hasLegacyArmour = !armour.legacyArmour.isZero() - - UserTipCard( - if (hasLegacyArmour) - UserTip.DEPRECATED_LEGACY_ARMOUR - else UserTip.ARMOUR_TRAPPINGS, - Modifier.padding(horizontal = 8.dp), - ) - - if (!hasLegacyArmour) { - return - } - - val change = { mutation: Armour.() -> Armour -> - onChange(with(armour.legacyArmour, mutation)) - } - - val strings = LocalStrings.current.armour - - CardContainer(Modifier.padding(horizontal = 8.dp)) { - CardTitle(strings.title) - val modifier = Modifier.fillMaxWidth() - - Row(modifier = modifier) { - ArmourPart( - icon = Resources.Drawable.ArmorShield, - name = strings.shield, - base = armour.armourFromItems.shield, - points = armour.legacyArmour.shield, - onChange = { change { copy(shield = it) } }, - modifier = Modifier.weight(1f), - ) - ArmourPart( - icon = Resources.Drawable.ArmorHead, - name = LocalStrings.current.combat.hitLocations.head, - base = armour.armourFromItems.head, - points = armour.legacyArmour.head, - rollRange = 1..9, - onChange = { change { copy(head = it) } }, - modifier = Modifier.weight(1f), - ) - Spacer(Modifier.weight(1f)) - } - - Row(modifier = modifier) { - ArmourPart( - icon = Resources.Drawable.ArmorArmRight, - name = LocalStrings.current.combat.hitLocations.rightArm, - base = armour.armourFromItems.rightArm, - points = armour.legacyArmour.rightArm, - rollRange = 25..44, - onChange = { change { copy(rightArm = it) } }, - modifier = Modifier.weight(1f), - ) - - ArmourPart( - icon = Resources.Drawable.ArmorChest, - name = LocalStrings.current.combat.hitLocations.body, - base = armour.armourFromItems.body, - points = armour.legacyArmour.body, - rollRange = 45..79, - onChange = { change { copy(body = it) } }, - modifier = Modifier.weight(1f), - ) - - ArmourPart( - icon = Resources.Drawable.ArmorArmLeft, - name = LocalStrings.current.combat.hitLocations.leftArm, - base = armour.armourFromItems.leftArm, - points = armour.legacyArmour.leftArm, - rollRange = 10..24, - onChange = { change { copy(leftArm = it) } }, - modifier = Modifier.weight(1f), - ) - } - - Row( - horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), - modifier = modifier - ) { - ArmourPart( - icon = Resources.Drawable.ArmorLegRight, - name = LocalStrings.current.combat.hitLocations.rightLeg, - base = armour.armourFromItems.rightLeg, - points = armour.legacyArmour.rightLeg, - rollRange = 90..100, - onChange = { change { copy(rightLeg = it) } }, - ) - - ArmourPart( - icon = Resources.Drawable.ArmorLegLeft, - name = LocalStrings.current.combat.hitLocations.leftLeg, - base = armour.armourFromItems.leftLeg, - points = armour.legacyArmour.leftLeg, - rollRange = 80..89, - onChange = { change { copy(leftLeg = it) } }, - ) - } - } -} - -@Composable -private fun ArmourPart( - icon: Resources.Drawable, - name: String, - points: Int, - base: Int, - modifier: Modifier = Modifier, - rollRange: IntRange? = null, - onChange: (Int) -> Unit, -) { - Column(horizontalAlignment = Alignment.CenterHorizontally, modifier = modifier) { - Icon(drawableResource(icon), VisualOnlyIconDescription) - NumberPicker( - value = base + points, - onIncrement = { - if (points < Armour.MAX_VALUE) { - onChange(points + 1) - } - }, - onDecrement = { - if (points > 0) { - onChange(points - 1) - } - }, - ) - - CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) { - Text(name) - - if (rollRange != null) { - Text("${formatRoll(rollRange.first)} - ${formatRoll(rollRange.last)}") - } - } - } -} - -private fun formatRoll(roll: Int): String = (roll % 100).toString().padStart(2, '0') diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreen.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreen.kt index 2054c27f6..9796d69fe 100644 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreen.kt +++ b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreen.kt @@ -36,6 +36,8 @@ import cz.frantisekmasa.wfrp_master.common.core.ui.dialogs.DialogState import cz.frantisekmasa.wfrp_master.common.core.ui.flow.collectWithLifecycle import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.EmptyUI import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.Spacing +import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.UserTip +import cz.frantisekmasa.wfrp_master.common.core.ui.primitives.UserTipCard import cz.frantisekmasa.wfrp_master.common.core.ui.scaffolding.TopPanel import cz.frantisekmasa.wfrp_master.common.localization.LocalStrings import kotlinx.coroutines.Dispatchers @@ -82,9 +84,7 @@ fun TrappingsScreen( } } - screenModel.armor.collectWithLifecycle(null).value?.let { armor -> - ArmourCard(armor, onChange = { screenModel.updateArmor(it) }) - } + UserTipCard(UserTip.ARMOUR_TRAPPINGS, Modifier.padding(horizontal = 8.dp)) var inventoryItemDialogState: DialogState by remember { mutableStateOf(DialogState.Closed()) diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreenModel.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreenModel.kt index 14f18eea8..a604a561c 100644 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreenModel.kt +++ b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/character/trappings/TrappingsScreenModel.kt @@ -1,14 +1,11 @@ package cz.frantisekmasa.wfrp_master.common.character.trappings -import androidx.compose.runtime.Immutable import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.coroutineScope import cz.frantisekmasa.wfrp_master.common.core.domain.Money -import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterFeatureRepository import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterRepository import cz.frantisekmasa.wfrp_master.common.core.domain.character.NotEnoughMoney import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId -import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.Armour import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.Encumbrance import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.InventoryItem import cz.frantisekmasa.wfrp_master.common.core.domain.trappings.InventoryItemRepository @@ -17,7 +14,6 @@ import cz.frantisekmasa.wfrp_master.common.core.shared.IO import cz.frantisekmasa.wfrp_master.common.core.utils.right import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -25,7 +21,6 @@ import kotlinx.coroutines.launch class TrappingsScreenModel( private val characterId: CharacterId, private val inventoryItems: InventoryItemRepository, - private val armorRepository: CharacterFeatureRepository, private val characters: CharacterRepository ) : ScreenModel { @@ -38,23 +33,6 @@ class TrappingsScreenModel( val totalEncumbrance: Flow = inventory .map { items -> items.map { it.effectiveEncumbrance }.sum() } - val armor: Flow = - armorRepository - .getLive(characterId) - .right() - .combine(inventory) { armour, items -> - EquippedArmour( - armourFromItems = Armour.fromItems(items), - legacyArmour = armour, - ) - } - - @Immutable - data class EquippedArmour( - val armourFromItems: Armour, - val legacyArmour: Armour, - ) - val money: Flow = character.map { it.money } suspend fun addMoney(amount: Money) { @@ -80,8 +58,4 @@ class TrappingsScreenModel( fun removeInventoryItem(inventoryItem: InventoryItem) = coroutineScope.launch(Dispatchers.IO) { inventoryItems.remove(characterId, inventoryItem.id) } - - fun updateArmor(armor: Armour) = coroutineScope.launch(Dispatchers.IO) { - armorRepository.save(characterId, armor) - } } diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/CharacterFeatureRepository.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/CharacterFeatureRepository.kt deleted file mode 100644 index ef38b37bf..000000000 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/CharacterFeatureRepository.kt +++ /dev/null @@ -1,12 +0,0 @@ -package cz.frantisekmasa.wfrp_master.common.core.domain.character - -import arrow.core.Either -import cz.frantisekmasa.wfrp_master.common.core.connectivity.CouldNotConnectToBackend -import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId -import kotlinx.coroutines.flow.Flow - -interface CharacterFeatureRepository { - suspend fun save(characterId: CharacterId, feature: T) - - fun getLive(characterId: CharacterId): Flow> -} diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/Feature.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/Feature.kt deleted file mode 100644 index c2e7cc6e4..000000000 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/domain/character/Feature.kt +++ /dev/null @@ -1,5 +0,0 @@ -package cz.frantisekmasa.wfrp_master.common.core.domain.character - -enum class Feature { - ARMOR -} diff --git a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/firebase/repositories/FirestoreCharacterFeatureRepository.kt b/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/firebase/repositories/FirestoreCharacterFeatureRepository.kt deleted file mode 100644 index 45d0da94f..000000000 --- a/common/src/commonMain/kotlin/cz/frantisekmasa/wfrp_master/common/core/firebase/repositories/FirestoreCharacterFeatureRepository.kt +++ /dev/null @@ -1,51 +0,0 @@ -package cz.frantisekmasa.wfrp_master.common.core.firebase.repositories - -import arrow.core.left -import arrow.core.right -import cz.frantisekmasa.wfrp_master.common.core.connectivity.CouldNotConnectToBackend -import cz.frantisekmasa.wfrp_master.common.core.domain.character.CharacterFeatureRepository -import cz.frantisekmasa.wfrp_master.common.core.domain.character.Feature -import cz.frantisekmasa.wfrp_master.common.core.domain.identifiers.CharacterId -import cz.frantisekmasa.wfrp_master.common.core.firebase.AggregateMapper -import cz.frantisekmasa.wfrp_master.common.core.firebase.Schema -import cz.frantisekmasa.wfrp_master.common.firebase.firestore.DocumentReference -import cz.frantisekmasa.wfrp_master.common.firebase.firestore.Firestore -import cz.frantisekmasa.wfrp_master.common.firebase.firestore.SetOptions -import io.github.aakira.napier.Napier -import kotlinx.coroutines.flow.map - -class FirestoreCharacterFeatureRepository( - feature: Feature, - firestore: Firestore, - private val defaultValue: T, - private val mapper: AggregateMapper -) : CharacterFeatureRepository { - - private val documentId = feature.name.lowercase() - private val parties = firestore.collection(Schema.Parties) - - override suspend fun save(characterId: CharacterId, feature: T) { - val data = mapper.toDocumentData(feature) - - Napier.d("Saving $documentId for character $characterId to firestore") - document(characterId).set(data, SetOptions.mergeFields(data.keys)) - } - - override fun getLive(characterId: CharacterId) = - document(characterId) - .snapshots - .map { snapshot -> - snapshot.fold( - { (it.data?.let(mapper::fromDocumentData) ?: defaultValue).right() }, - { CouldNotConnectToBackend(it).left() }, - ) - } - - private fun document(characterId: CharacterId): DocumentReference { - return parties.document(characterId.partyId.toString()) - .collection(Schema.Characters) - .document(characterId.id) - .collection(Schema.CharacterFeatures) - .document(documentId) - } -} diff --git a/firebase/migrations/v0.0.6__drop_legacy_armour.ts b/firebase/migrations/v0.0.6__drop_legacy_armour.ts index e7abf3550..b5d50265d 100644 --- a/firebase/migrations/v0.0.6__drop_legacy_armour.ts +++ b/firebase/migrations/v0.0.6__drop_legacy_armour.ts @@ -11,9 +11,7 @@ const ARMOUR_PARTS = { }; export async function migrate({firestore}: { firestore: firebase.firestore.Firestore }): Promise { - const characters = await firestore.collection("parties").doc("bbc08a6e-38dd-48de-8608-0e5461c5d190") - .collection("characters").get(); - //const characters = await firestore.collectionGroup("characters").get(); + const characters = await firestore.collectionGroup("characters").get(); for (const document of characters.docs) { const character = document.data();