Add dice roll sharing
This commit is contained in:
		
							parent
							
								
									41a094009d
								
							
						
					
					
						commit
						980a7e7929
					
				
					 37 changed files with 745 additions and 327 deletions
				
			
		
							
								
								
									
										2
									
								
								app/proguard-rules.pro
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								app/proguard-rules.pro
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -35,4 +35,4 @@
 | 
				
			||||||
# This rule will properly ProGuard all the model classes in
 | 
					# This rule will properly ProGuard all the model classes in
 | 
				
			||||||
# the package com.yourcompany.models.
 | 
					# the package com.yourcompany.models.
 | 
				
			||||||
# Modify this rule to fit the structure of your app.
 | 
					# Modify this rule to fit the structure of your app.
 | 
				
			||||||
-keepclassmembers class com.pixelized.rplexicon.data.model.CharacterSheetFire.** { *; }
 | 
					-keepclassmembers class com.pixelized.rplexicon.data.network.CharacterSheetFire.** { *; }
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,8 @@ import com.pixelized.rplexicon.data.model.DiceThrow
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Property
 | 
					import com.pixelized.rplexicon.data.model.Property
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Skill
 | 
					import com.pixelized.rplexicon.data.model.Skill
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Throw
 | 
					import com.pixelized.rplexicon.data.model.Throw
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrow
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrow.Bonus
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.ActionRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
				
			||||||
| 
						 | 
					@ -38,6 +40,7 @@ import kotlin.math.min
 | 
				
			||||||
data class DiceThrowResult(
 | 
					data class DiceThrowResult(
 | 
				
			||||||
    val dice: RollDiceUio,
 | 
					    val dice: RollDiceUio,
 | 
				
			||||||
    val card: ThrowsCardUio,
 | 
					    val card: ThrowsCardUio,
 | 
				
			||||||
 | 
					    val network: NetworkThrow,
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Suppress("KotlinConstantConditions")
 | 
					@Suppress("KotlinConstantConditions")
 | 
				
			||||||
| 
						 | 
					@ -664,7 +667,19 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                            result = "${result.value}",
 | 
					                            result = "${result.value}",
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus + mastery,
 | 
					                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus + mastery,
 | 
				
			||||||
                )
 | 
					                ),
 | 
				
			||||||
 | 
					                network = NetworkThrow(
 | 
				
			||||||
 | 
					                    timestamp = System.currentTimeMillis(),
 | 
				
			||||||
 | 
					                    title = abilityTitleString.uppercase(),
 | 
				
			||||||
 | 
					                    result = rollResult,
 | 
				
			||||||
 | 
					                    isCriticalSuccess = if (result.value == 20) true else null,
 | 
				
			||||||
 | 
					                    isCriticalFailure = if (result.value == 1) true else null,
 | 
				
			||||||
 | 
					                    details = bonus(abilityTitleString, "1d20", result.label) +
 | 
				
			||||||
 | 
					                            diceAlterationBonus.detail() +
 | 
				
			||||||
 | 
					                            flatAlterationBonus.detail() +
 | 
				
			||||||
 | 
					                            relatedStatBonus.detail() +
 | 
				
			||||||
 | 
					                            mastery.detail()
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -771,7 +786,19 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                            result = "${result.value}",
 | 
					                            result = "${result.value}",
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus + flatBonus,
 | 
					                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus + flatBonus,
 | 
				
			||||||
                )
 | 
					                ),
 | 
				
			||||||
 | 
					                network = NetworkThrow(
 | 
				
			||||||
 | 
					                    timestamp = System.currentTimeMillis(),
 | 
				
			||||||
 | 
					                    title = titleString.uppercase(),
 | 
				
			||||||
 | 
					                    result = rollResult,
 | 
				
			||||||
 | 
					                    isCriticalSuccess = if (canMakeCriticalRoll && result.value == 20) true else null,
 | 
				
			||||||
 | 
					                    isCriticalFailure = if (canMakeCriticalRoll && result.value == 1) true else null,
 | 
				
			||||||
 | 
					                    details = bonus(
 | 
				
			||||||
 | 
					                        title = titleString,
 | 
				
			||||||
 | 
					                        dice = "${diceThrow?.amount}d${diceThrow?.faces}",
 | 
				
			||||||
 | 
					                        result = result.label
 | 
				
			||||||
 | 
					                    ) + diceAlterationBonus.detail() + flatAlterationBonus.detail() + relatedStatBonus.detail() + flatBonus.detail()
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -857,7 +884,17 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                            result = "${result.value}",
 | 
					                            result = "${result.value}",
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    ) + levelBonus + relatedStatBonus,
 | 
					                    ) + levelBonus + relatedStatBonus,
 | 
				
			||||||
                )
 | 
					                ),
 | 
				
			||||||
 | 
					                network = NetworkThrow(
 | 
				
			||||||
 | 
					                    timestamp = System.currentTimeMillis(),
 | 
				
			||||||
 | 
					                    title = titleString.uppercase(),
 | 
				
			||||||
 | 
					                    result = rollResult,
 | 
				
			||||||
 | 
					                    details = bonus(
 | 
				
			||||||
 | 
					                        title = titleString,
 | 
				
			||||||
 | 
					                        dice = "${spell?.effect?.amount}d${spell?.effect?.faces}",
 | 
				
			||||||
 | 
					                        result = result.label
 | 
				
			||||||
 | 
					                    ) + levelBonus.detail() + relatedStatBonus.detail()
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					@ -904,13 +941,13 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                ),
 | 
					                ),
 | 
				
			||||||
                card = ThrowsCardUio(
 | 
					                card = ThrowsCardUio(
 | 
				
			||||||
                    title = titleString.uppercase(),
 | 
					                    title = titleString.uppercase(),
 | 
				
			||||||
                    highlight = spellName,
 | 
					                    highlight = spellName ?: "",
 | 
				
			||||||
                    dice = (skill?.effect?.faces ?: 4).icon,
 | 
					                    dice = (skill?.effect?.faces ?: 4).icon,
 | 
				
			||||||
                    roll = allValue.toLabel(),
 | 
					                    roll = allValue.toLabel(),
 | 
				
			||||||
                    result = rollResult,
 | 
					                    result = rollResult,
 | 
				
			||||||
                    details = listOf(
 | 
					                    details = listOf(
 | 
				
			||||||
                        ThrowsCardUio.Detail(
 | 
					                        ThrowsCardUio.Detail(
 | 
				
			||||||
                            title = spellName,
 | 
					                            title = spellName ?: "",
 | 
				
			||||||
                            throws = ThrowsCardUio.Throw(
 | 
					                            throws = ThrowsCardUio.Throw(
 | 
				
			||||||
                                dice = (skill?.effect?.faces ?: 4).icon,
 | 
					                                dice = (skill?.effect?.faces ?: 4).icon,
 | 
				
			||||||
                                roll = "${skill?.effect?.amount ?: 1}d${skill?.effect?.faces ?: 4}",
 | 
					                                roll = "${skill?.effect?.amount ?: 1}d${skill?.effect?.faces ?: 4}",
 | 
				
			||||||
| 
						 | 
					@ -921,11 +958,27 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                            result = "${result.value}",
 | 
					                            result = "${result.value}",
 | 
				
			||||||
                        ),
 | 
					                        ),
 | 
				
			||||||
                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus,
 | 
					                    ) + diceAlterationBonus + flatAlterationBonus + relatedStatBonus,
 | 
				
			||||||
                )
 | 
					                ),
 | 
				
			||||||
 | 
					                network = NetworkThrow(
 | 
				
			||||||
 | 
					                    timestamp = System.currentTimeMillis(),
 | 
				
			||||||
 | 
					                    title = titleString.uppercase(),
 | 
				
			||||||
 | 
					                    result = rollResult,
 | 
				
			||||||
 | 
					                    details = bonus(
 | 
				
			||||||
 | 
					                        title = titleString,
 | 
				
			||||||
 | 
					                        dice = "${skill?.effect?.amount}d${skill?.effect?.faces}",
 | 
				
			||||||
 | 
					                        result = result.label
 | 
				
			||||||
 | 
					                    ) + diceAlterationBonus.detail() + flatAlterationBonus.detail() + relatedStatBonus.detail()
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun bonus(title: String, dice: String, result: String): List<Bonus> =
 | 
				
			||||||
 | 
					        listOf(Bonus(title, dice, result))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private fun List<ThrowsCardUio.Detail>.detail(): List<Bonus> =
 | 
				
			||||||
 | 
					        map { Bonus(it.title, it.throws?.roll, it.result) }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Helper class to track rolls and declare helper method.
 | 
					     * Helper class to track rolls and declare helper method.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
| 
						 | 
					@ -994,7 +1047,7 @@ class DiceThrowUseCase @Inject constructor(
 | 
				
			||||||
                        critical = status.critical,
 | 
					                        critical = status.critical,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    ThrowsCardUio.Detail(
 | 
					                    ThrowsCardUio.Detail(
 | 
				
			||||||
                        title = dice.title,
 | 
					                        title = dice.title ?: "",
 | 
				
			||||||
                        throws = ThrowsCardUio.Throw(
 | 
					                        throws = ThrowsCardUio.Throw(
 | 
				
			||||||
                            dice = dice.faces.icon,
 | 
					                            dice = dice.faces.icon,
 | 
				
			||||||
                            advantage = dice.advantage,
 | 
					                            advantage = dice.advantage,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ package com.pixelized.rplexicon.business
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
					import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
 | 
					import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
					import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.character.factory.SpellUioFactory
 | 
					import com.pixelized.rplexicon.ui.screens.character.factory.SpellUioFactory
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.data.model
 | 
					package com.pixelized.rplexicon.data.network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.annotation.Keep
 | 
					import androidx.annotation.Keep
 | 
				
			||||||
import com.google.firebase.database.IgnoreExtraProperties
 | 
					import com.google.firebase.database.IgnoreExtraProperties
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.data.model
 | 
					package com.pixelized.rplexicon.data.network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.annotation.Keep
 | 
					import androidx.annotation.Keep
 | 
				
			||||||
import com.google.firebase.database.IgnoreExtraProperties
 | 
					import com.google.firebase.database.IgnoreExtraProperties
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,64 @@
 | 
				
			||||||
 | 
					package com.pixelized.rplexicon.data.network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.annotation.Keep
 | 
				
			||||||
 | 
					import com.google.firebase.database.IgnoreExtraProperties
 | 
				
			||||||
 | 
					import com.google.firebase.database.PropertyName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Keep
 | 
				
			||||||
 | 
					@IgnoreExtraProperties
 | 
				
			||||||
 | 
					data class NetworkThrow(
 | 
				
			||||||
 | 
					    @get:PropertyName(TIMESTAMP)
 | 
				
			||||||
 | 
					    @set:PropertyName(TIMESTAMP)
 | 
				
			||||||
 | 
					    var timestamp: Long = 0L,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @get:PropertyName(TITLE)
 | 
				
			||||||
 | 
					    @set:PropertyName(TITLE)
 | 
				
			||||||
 | 
					    var title: String = "",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @get:PropertyName(RESULT)
 | 
				
			||||||
 | 
					    @set:PropertyName(RESULT)
 | 
				
			||||||
 | 
					    var result: String = "",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @get:PropertyName(CRITICAL)
 | 
				
			||||||
 | 
					    @set:PropertyName(CRITICAL)
 | 
				
			||||||
 | 
					    var isCriticalSuccess: Boolean? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @get:PropertyName(FAIL)
 | 
				
			||||||
 | 
					    @set:PropertyName(FAIL)
 | 
				
			||||||
 | 
					    var isCriticalFailure: Boolean? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @get:PropertyName(DETAILS)
 | 
				
			||||||
 | 
					    @set:PropertyName(DETAILS)
 | 
				
			||||||
 | 
					    var details: List<Bonus> = emptyList(),
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    @Keep
 | 
				
			||||||
 | 
					    @IgnoreExtraProperties
 | 
				
			||||||
 | 
					    data class Bonus(
 | 
				
			||||||
 | 
					        @get:PropertyName(LABEL)
 | 
				
			||||||
 | 
					        @set:PropertyName(LABEL)
 | 
				
			||||||
 | 
					        var label: String = "",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @get:PropertyName(DICE)
 | 
				
			||||||
 | 
					        @set:PropertyName(DICE)
 | 
				
			||||||
 | 
					        var dice: String? = null,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        @get:PropertyName(RESULT)
 | 
				
			||||||
 | 
					        @set:PropertyName(RESULT)
 | 
				
			||||||
 | 
					        var result: String = "",
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        companion object {
 | 
				
			||||||
 | 
					            const val LABEL = "label"
 | 
				
			||||||
 | 
					            const val DICE = "dice"
 | 
				
			||||||
 | 
					            const val RESULT = "result"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        const val TIMESTAMP = "timestamp"
 | 
				
			||||||
 | 
					        const val TITLE = "title"
 | 
				
			||||||
 | 
					        const val RESULT = "result"
 | 
				
			||||||
 | 
					        const val CRITICAL = "crit"
 | 
				
			||||||
 | 
					        const val FAIL = "fail"
 | 
				
			||||||
 | 
					        const val DETAILS = "details"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,17 @@
 | 
				
			||||||
 | 
					package com.pixelized.rplexicon.data.network
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.annotation.Keep
 | 
				
			||||||
 | 
					import com.google.firebase.database.IgnoreExtraProperties
 | 
				
			||||||
 | 
					import com.google.firebase.database.PropertyName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Keep
 | 
				
			||||||
 | 
					@IgnoreExtraProperties
 | 
				
			||||||
 | 
					data class NetworkThrowMap(
 | 
				
			||||||
 | 
					    @get:PropertyName(CHARACTERS_THROWS)
 | 
				
			||||||
 | 
					    @set:PropertyName(CHARACTERS_THROWS)
 | 
				
			||||||
 | 
					    var details: Map<String, NetworkThrow> = emptyMap(),
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        const val CHARACTERS_THROWS = "CharactersThrows"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,8 +8,11 @@ import com.google.firebase.database.ValueEventListener
 | 
				
			||||||
import com.google.firebase.database.ktx.database
 | 
					import com.google.firebase.database.ktx.database
 | 
				
			||||||
import com.google.firebase.ktx.Firebase
 | 
					import com.google.firebase.ktx.Firebase
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFireMap
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFireMap
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrow
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrowMap
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrowMap.Companion.CHARACTERS_THROWS
 | 
				
			||||||
import kotlinx.coroutines.CoroutineScope
 | 
					import kotlinx.coroutines.CoroutineScope
 | 
				
			||||||
import kotlinx.coroutines.Dispatchers
 | 
					import kotlinx.coroutines.Dispatchers
 | 
				
			||||||
import kotlinx.coroutines.Job
 | 
					import kotlinx.coroutines.Job
 | 
				
			||||||
| 
						 | 
					@ -167,8 +170,46 @@ class FirebaseRepository @Inject constructor(
 | 
				
			||||||
        reference.setValue(value)
 | 
					        reference.setValue(value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun sendThrow(character: String?, throws: NetworkThrow) {
 | 
				
			||||||
 | 
					        character?.let {
 | 
				
			||||||
 | 
					            val reference = database.getReference("$PATH_THROWS/")
 | 
				
			||||||
 | 
					            reference.updateChildren(mapOf(it to throws))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fun getThrows(): Flow<NetworkThrowMap> {
 | 
				
			||||||
 | 
					        return callbackFlow {
 | 
				
			||||||
 | 
					            // reference to the node
 | 
				
			||||||
 | 
					            val reference = database.getReference("/")
 | 
				
			||||||
 | 
					            // build a register the callback
 | 
				
			||||||
 | 
					            val listener = reference.addValueEventListener(object : ValueEventListener {
 | 
				
			||||||
 | 
					                override fun onDataChange(dataSnapshot: DataSnapshot) {
 | 
				
			||||||
 | 
					                    val value = try {
 | 
				
			||||||
 | 
					                        dataSnapshot.getValue(NetworkThrowMap::class.java)
 | 
				
			||||||
 | 
					                    } catch (exception: Exception) {
 | 
				
			||||||
 | 
					                        Log.e(TAG, "Failed to parse value.", exception)
 | 
				
			||||||
 | 
					                        _error.tryEmit(exception)
 | 
				
			||||||
 | 
					                        null
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (value != null) {
 | 
				
			||||||
 | 
					                        trySend(value)
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                override fun onCancelled(error: DatabaseError) {
 | 
				
			||||||
 | 
					                    Log.e(TAG, "Failed to read value.", error.toException())
 | 
				
			||||||
 | 
					                    cancel()
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            awaitClose {
 | 
				
			||||||
 | 
					                reference.removeEventListener(listener)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    companion object {
 | 
					    companion object {
 | 
				
			||||||
        private const val TAG = "FirebaseRepository"
 | 
					        private const val TAG = "FirebaseRepository"
 | 
				
			||||||
        private const val PATH_CHARACTERS = "Characters"
 | 
					        private const val PATH_CHARACTERS = "Characters"
 | 
				
			||||||
 | 
					        private const val PATH_THROWS = CHARACTERS_THROWS
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2,15 +2,11 @@ package com.pixelized.rplexicon.ui.screens.character.factory
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
					import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Property
 | 
					import com.pixelized.rplexicon.data.model.Property
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellHeaderUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
					import com.pixelized.rplexicon.ui.screens.character.composable.actions.SpellUio
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.icon
 | 
					import com.pixelized.rplexicon.utilitary.extentions.icon
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.firstSpellSlot
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.icon
 | 
					import com.pixelized.rplexicon.utilitary.extentions.local.icon
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.spell
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.modifier
 | 
					import com.pixelized.rplexicon.utilitary.extentions.modifier
 | 
				
			||||||
import javax.inject.Inject
 | 
					import javax.inject.Inject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,7 @@ import androidx.lifecycle.AndroidViewModel
 | 
				
			||||||
import androidx.lifecycle.SavedStateHandle
 | 
					import androidx.lifecycle.SavedStateHandle
 | 
				
			||||||
import androidx.lifecycle.viewModelScope
 | 
					import androidx.lifecycle.viewModelScope
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
					import com.pixelized.rplexicon.data.model.DiceThrow
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Property
 | 
					import com.pixelized.rplexicon.data.model.Property
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Skill
 | 
					import com.pixelized.rplexicon.data.model.Skill
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,7 +10,7 @@ import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.business.SpellBookUseCase
 | 
					import com.pixelized.rplexicon.business.SpellBookUseCase
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
					import com.pixelized.rplexicon.data.model.AssignedSpell
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
					import com.pixelized.rplexicon.data.model.DiceThrow
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Property
 | 
					import com.pixelized.rplexicon.data.model.Property
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Throw
 | 
					import com.pixelized.rplexicon.data.model.Throw
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -287,9 +287,9 @@ private fun RollOverlayContent(
 | 
				
			||||||
                                )
 | 
					                                )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                else -> ThrowsCard(
 | 
					                                else -> ThrowsCard(
 | 
				
			||||||
                                    modifier = Modifier.padding(
 | 
					                                    modifier = Modifier
 | 
				
			||||||
                                        bottom = if (enableDrawer.value) 32.dp else 0.dp
 | 
					                                        .padding(bottom = if (enableDrawer.value) 32.dp else 0.dp)
 | 
				
			||||||
                                    ),
 | 
					                                        .padding(all = 16.dp),
 | 
				
			||||||
                                    throws = it,
 | 
					                                    throws = it,
 | 
				
			||||||
                                    showDetail = showDetail,
 | 
					                                    showDetail = showDetail,
 | 
				
			||||||
                                    onClick = onCard,
 | 
					                                    onClick = onCard,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -10,6 +10,7 @@ import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.business.DiceThrowUseCase
 | 
					import com.pixelized.rplexicon.business.DiceThrowUseCase
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.DiceThrow
 | 
					import com.pixelized.rplexicon.data.model.DiceThrow
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.DescriptionRepository
 | 
				
			||||||
| 
						 | 
					@ -36,6 +37,7 @@ class RollOverlayViewModel @Inject constructor(
 | 
				
			||||||
    private val rollUseCase: DiceThrowUseCase,
 | 
					    private val rollUseCase: DiceThrowUseCase,
 | 
				
			||||||
    private val diceFactory: DiceFactory,
 | 
					    private val diceFactory: DiceFactory,
 | 
				
			||||||
    private val alterationFactory: AlterationFactory,
 | 
					    private val alterationFactory: AlterationFactory,
 | 
				
			||||||
 | 
					    private val firebaseRepository: FirebaseRepository,
 | 
				
			||||||
    application: Application,
 | 
					    application: Application,
 | 
				
			||||||
) : AndroidViewModel(application) {
 | 
					) : AndroidViewModel(application) {
 | 
				
			||||||
    private var sheet: CharacterSheet? = null
 | 
					    private var sheet: CharacterSheet? = null
 | 
				
			||||||
| 
						 | 
					@ -88,13 +90,19 @@ class RollOverlayViewModel @Inject constructor(
 | 
				
			||||||
        diceThrow?.let { diceThrow ->
 | 
					        diceThrow?.let { diceThrow ->
 | 
				
			||||||
            rollJob?.cancel()
 | 
					            rollJob?.cancel()
 | 
				
			||||||
            rollJob = viewModelScope.launch {
 | 
					            rollJob = viewModelScope.launch {
 | 
				
			||||||
 | 
					                // roll the dice ;)
 | 
				
			||||||
                val result = rollUseCase.roll(
 | 
					                val result = rollUseCase.roll(
 | 
				
			||||||
                    diceThrow = diceThrow,
 | 
					                    diceThrow = diceThrow,
 | 
				
			||||||
                    alterationId = _alterations.value.mapNotNull { if (it.checked) it.label else null },
 | 
					                    alterationId = _alterations.value.mapNotNull { if (it.checked) it.label else null },
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
 | 
					                // share the result
 | 
				
			||||||
 | 
					                result?.network?.let {
 | 
				
			||||||
 | 
					                    firebaseRepository.sendThrow(sheet?.name, it)
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
                // Start the roll animation.
 | 
					                // Start the roll animation.
 | 
				
			||||||
                _dice.value = _dice.value?.let {
 | 
					                _dice.value = _dice.value?.let {
 | 
				
			||||||
                    it.copy(
 | 
					                    it.copy(
 | 
				
			||||||
 | 
					                        result = "",
 | 
				
			||||||
                        animationSpec = RollDiceUio.TWEEN,
 | 
					                        animationSpec = RollDiceUio.TWEEN,
 | 
				
			||||||
                        rotation = it.rotation + 5f,
 | 
					                        rotation = it.rotation + 5f,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ import java.util.UUID
 | 
				
			||||||
@Stable
 | 
					@Stable
 | 
				
			||||||
data class ThrowsCardUio(
 | 
					data class ThrowsCardUio(
 | 
				
			||||||
    val id: String = UUID.randomUUID().toString(),
 | 
					    val id: String = UUID.randomUUID().toString(),
 | 
				
			||||||
    val title: String?,                     // the roll title
 | 
					    val title: String,                     // the roll title
 | 
				
			||||||
    val highlight: String?,                 // the highlighted part of the title
 | 
					    val highlight: String?,                 // the highlighted part of the title
 | 
				
			||||||
    @DrawableRes val dice: Int?,            // the dice icon
 | 
					    @DrawableRes val dice: Int?,            // the dice icon
 | 
				
			||||||
    val roll: String,                       // the roll + bonus string.
 | 
					    val roll: String,                       // the roll + bonus string.
 | 
				
			||||||
| 
						 | 
					@ -66,7 +66,7 @@ data class ThrowsCardUio(
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    @Stable
 | 
					    @Stable
 | 
				
			||||||
    data class Detail(
 | 
					    data class Detail(
 | 
				
			||||||
        val title: String? = null,          // the detail title
 | 
					        val title: String = "",          // the detail title
 | 
				
			||||||
        val throws: Throw? = null,          // the detail of the roll if any
 | 
					        val throws: Throw? = null,          // the detail of the roll if any
 | 
				
			||||||
        val result: String,                 // the result
 | 
					        val result: String,                 // the result
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
| 
						 | 
					@ -104,7 +104,6 @@ fun ThrowsCard(
 | 
				
			||||||
    Surface(
 | 
					    Surface(
 | 
				
			||||||
        modifier = modifier
 | 
					        modifier = modifier
 | 
				
			||||||
            .fillMaxWidth()
 | 
					            .fillMaxWidth()
 | 
				
			||||||
            .padding(all = 16.dp)
 | 
					 | 
				
			||||||
            .ddBorder(inner = inner, outline = remember { CutCornerShape(size = 16.dp) })
 | 
					            .ddBorder(inner = inner, outline = remember { CutCornerShape(size = 16.dp) })
 | 
				
			||||||
            .clip(shape = inner)
 | 
					            .clip(shape = inner)
 | 
				
			||||||
            .clickable(onClick = onClick),
 | 
					            .clickable(onClick = onClick),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,9 @@ import androidx.compose.runtime.mutableIntStateOf
 | 
				
			||||||
import androidx.compose.runtime.mutableStateOf
 | 
					import androidx.compose.runtime.mutableStateOf
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.data.model.Property
 | 
					import com.pixelized.rplexicon.data.model.Property
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.data.network.NetworkThrow
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
					import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.AlterationRepository
 | 
				
			||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
					import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
 | 
				
			||||||
| 
						 | 
					@ -21,6 +22,7 @@ import com.pixelized.rplexicon.ui.screens.summary.composable.common.label
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.maxLabel
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.maxLabel
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.none
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.none
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.proficiency
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.proficiency
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummaryUio
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.highestSpellLevel
 | 
					import com.pixelized.rplexicon.utilitary.extentions.local.highestSpellLevel
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.mastery
 | 
					import com.pixelized.rplexicon.utilitary.extentions.local.mastery
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.local.passivesBonus
 | 
					import com.pixelized.rplexicon.utilitary.extentions.local.passivesBonus
 | 
				
			||||||
| 
						 | 
					@ -45,7 +47,7 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
    private val alterationRepository: AlterationRepository,
 | 
					    private val alterationRepository: AlterationRepository,
 | 
				
			||||||
    private val firebaseRepository: FirebaseRepository,
 | 
					    private val firebaseRepository: FirebaseRepository,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    fun fetchSummary(scope: CoroutineScope): SummaryUio {
 | 
					    fun fetchSummary(scope: CoroutineScope): StatisticSummaryUio {
 | 
				
			||||||
        val headerVisibility = mutableStateOf(false)
 | 
					        val headerVisibility = mutableStateOf(false)
 | 
				
			||||||
        val statsVisibility = mutableStateOf(false)
 | 
					        val statsVisibility = mutableStateOf(false)
 | 
				
			||||||
        val characteristicsVisibility = mutableStateOf(false)
 | 
					        val characteristicsVisibility = mutableStateOf(false)
 | 
				
			||||||
| 
						 | 
					@ -55,13 +57,18 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
        val spellsVisibility = mutableStateOf(false)
 | 
					        val spellsVisibility = mutableStateOf(false)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        val header = ClassHeaderSummaryUio(
 | 
					        val header = ClassHeaderSummaryUio(
 | 
				
			||||||
            c1 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
					            clazz1 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
				
			||||||
            c2 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
					            dice1 = mutableStateOf(ClassHeaderSummaryUio.Dice()),
 | 
				
			||||||
            c3 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
					            clazz2 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
				
			||||||
            c4 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
					            dice2 = mutableStateOf(ClassHeaderSummaryUio.Dice()),
 | 
				
			||||||
            c5 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
					            clazz3 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
				
			||||||
 | 
					            dice3 = mutableStateOf(ClassHeaderSummaryUio.Dice()),
 | 
				
			||||||
 | 
					            clazz4 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
				
			||||||
 | 
					            dice4 = mutableStateOf(ClassHeaderSummaryUio.Dice()),
 | 
				
			||||||
 | 
					            clazz5 = mutableStateOf(ClassHeaderSummaryUio.Header()),
 | 
				
			||||||
 | 
					            dice5 = mutableStateOf(ClassHeaderSummaryUio.Dice()),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        val stats = AttributesSummaryUio(
 | 
					        val attributes = AttributesSummaryUio(
 | 
				
			||||||
            hp = SummaryRowUio(label = R.string.character_sheet_title_hp),
 | 
					            hp = SummaryRowUio(label = R.string.character_sheet_title_hp),
 | 
				
			||||||
            ac = SummaryRowUio(label = R.string.character_sheet_title_ca),
 | 
					            ac = SummaryRowUio(label = R.string.character_sheet_title_ca),
 | 
				
			||||||
            dc = SummaryRowUio(label = R.string.character_sheet_title_dc),
 | 
					            dc = SummaryRowUio(label = R.string.character_sheet_title_dc),
 | 
				
			||||||
| 
						 | 
					@ -143,24 +150,12 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
                        maxSpellSlot.intValue = highestSpellSlot
 | 
					                        maxSpellSlot.intValue = highestSpellSlot
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // extension function to root a character to a column property.
 | 
					                    // extension functions to root a character to a column property.
 | 
				
			||||||
                    fun ClassHeaderSummaryUio.get(sheet: CharacterSheet?) = when (sheet) {
 | 
					                    fun SummaryRowUio.get(sheet: CharacterSheet?) =
 | 
				
			||||||
                        sheets[characters.getOrNull(0)] -> c1
 | 
					                        get(index = characters.indexOf(sheet?.name))
 | 
				
			||||||
                        sheets[characters.getOrNull(1)] -> c2
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(2)] -> c3
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(3)] -> c4
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(4)] -> c5
 | 
					 | 
				
			||||||
                        else -> null
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    fun SummaryRowUio.get(sheet: CharacterSheet?) = when (sheet) {
 | 
					                    fun ClassHeaderSummaryUio.getClass(sheet: CharacterSheet?) =
 | 
				
			||||||
                        sheets[characters.getOrNull(0)] -> c1
 | 
					                        classes.getOrNull(index = characters.indexOf(sheet?.name))
 | 
				
			||||||
                        sheets[characters.getOrNull(1)] -> c2
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(2)] -> c3
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(3)] -> c4
 | 
					 | 
				
			||||||
                        sheets[characters.getOrNull(4)] -> c5
 | 
					 | 
				
			||||||
                        else -> null
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    // Update the header
 | 
					                    // Update the header
 | 
				
			||||||
                    sheets.values.forEach { sheet ->
 | 
					                    sheets.values.forEach { sheet ->
 | 
				
			||||||
| 
						 | 
					@ -169,7 +164,7 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
                            icon = sheet.characterClass.firstOrNull()?.icon ?: R.drawable.ic_d20_24,
 | 
					                            icon = sheet.characterClass.firstOrNull()?.icon ?: R.drawable.ic_d20_24,
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        withContext(Dispatchers.Main) {
 | 
					                        withContext(Dispatchers.Main) {
 | 
				
			||||||
                            header.get(sheet)?.value = clazz
 | 
					                            header.getClass(sheet)?.value = clazz
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    withContext(Dispatchers.Main) {
 | 
					                    withContext(Dispatchers.Main) {
 | 
				
			||||||
| 
						 | 
					@ -206,11 +201,11 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
                            label = "${sheet.speed}m",
 | 
					                            label = "${sheet.speed}m",
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                        withContext(Dispatchers.Main) {
 | 
					                        withContext(Dispatchers.Main) {
 | 
				
			||||||
                            stats.hp.get(sheet)?.value = hitPoint
 | 
					                            attributes.hp.get(sheet)?.value = hitPoint
 | 
				
			||||||
                            stats.ac.get(sheet)?.value = armorClass
 | 
					                            attributes.ac.get(sheet)?.value = armorClass
 | 
				
			||||||
                            stats.dc.get(sheet)?.value = dC
 | 
					                            attributes.dc.get(sheet)?.value = dC
 | 
				
			||||||
                            stats.initiative.get(sheet)?.value = initiative
 | 
					                            attributes.initiative.get(sheet)?.value = initiative
 | 
				
			||||||
                            stats.speed.get(sheet)?.value = speed
 | 
					                            attributes.speed.get(sheet)?.value = speed
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    withContext(Dispatchers.Main) {
 | 
					                    withContext(Dispatchers.Main) {
 | 
				
			||||||
| 
						 | 
					@ -609,11 +604,36 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return SummaryUio(
 | 
					        scope.launch(Dispatchers.IO) {
 | 
				
			||||||
 | 
					            val data = HeaderStatStruct()
 | 
				
			||||||
 | 
					            characterSheetRepository.data
 | 
				
			||||||
 | 
					                .combine(firebaseRepository.getThrows()) { sheets, fire ->
 | 
				
			||||||
 | 
					                    data.sheets = sheets
 | 
				
			||||||
 | 
					                    data.fires = fire.details
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                .collect {
 | 
				
			||||||
 | 
					                    val (sheets, throws) = data
 | 
				
			||||||
 | 
					                    val characters = sheets.keys.sorted()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    fun ClassHeaderSummaryUio.getDice(name: String?) =
 | 
				
			||||||
 | 
					                        dices.getOrNull(index = characters.indexOf(name))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    throws.forEach { entry ->
 | 
				
			||||||
 | 
					                        header.getDice(name = entry.key)?.value = ClassHeaderSummaryUio.Dice(
 | 
				
			||||||
 | 
					                            timestamp = entry.value.timestamp,
 | 
				
			||||||
 | 
					                            result = entry.value.result,
 | 
				
			||||||
 | 
					                            isCriticalSuccess = entry.value.isCriticalSuccess ?: false,
 | 
				
			||||||
 | 
					                            isCriticalFailure = entry.value.isCriticalFailure ?: false,
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return StatisticSummaryUio(
 | 
				
			||||||
            headerVisibility = headerVisibility,
 | 
					            headerVisibility = headerVisibility,
 | 
				
			||||||
            header = header,
 | 
					            header = header,
 | 
				
			||||||
            statsVisibility = statsVisibility,
 | 
					            statsVisibility = statsVisibility,
 | 
				
			||||||
            stats = stats,
 | 
					            attributes = attributes,
 | 
				
			||||||
            characteristicsVisibility = characteristicsVisibility,
 | 
					            characteristicsVisibility = characteristicsVisibility,
 | 
				
			||||||
            characteristics = characteristics,
 | 
					            characteristics = characteristics,
 | 
				
			||||||
            savingThrowsVisibility = savingThrowsVisibility,
 | 
					            savingThrowsVisibility = savingThrowsVisibility,
 | 
				
			||||||
| 
						 | 
					@ -634,4 +654,12 @@ class SummaryFactory @Inject constructor(
 | 
				
			||||||
        operator fun component1() = sheets
 | 
					        operator fun component1() = sheets
 | 
				
			||||||
        operator fun component2() = fires
 | 
					        operator fun component2() = fires
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private class HeaderStatStruct {
 | 
				
			||||||
 | 
					        lateinit var sheets: Map<String, CharacterSheet>
 | 
				
			||||||
 | 
					        lateinit var fires: Map<String, NetworkThrow>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        operator fun component1() = sheets
 | 
				
			||||||
 | 
					        operator fun component2() = fires
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,22 +1,18 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary
 | 
					package com.pixelized.rplexicon.ui.screens.summary
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.content.res.Configuration
 | 
					import android.content.res.Configuration
 | 
				
			||||||
import androidx.compose.animation.AnimatedVisibility
 | 
					import androidx.compose.foundation.ExperimentalFoundationApi
 | 
				
			||||||
import androidx.compose.animation.EnterTransition
 | 
					 | 
				
			||||||
import androidx.compose.animation.fadeIn
 | 
					 | 
				
			||||||
import androidx.compose.animation.slideInVertically
 | 
					 | 
				
			||||||
import androidx.compose.foundation.ScrollState
 | 
					 | 
				
			||||||
import androidx.compose.foundation.background
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.Arrangement
 | 
					import androidx.compose.foundation.layout.Arrangement
 | 
				
			||||||
import androidx.compose.foundation.layout.Column
 | 
					import androidx.compose.foundation.layout.Column
 | 
				
			||||||
import androidx.compose.foundation.layout.Row
 | 
					import androidx.compose.foundation.layout.Row
 | 
				
			||||||
import androidx.compose.foundation.layout.fillMaxSize
 | 
					import androidx.compose.foundation.layout.fillMaxSize
 | 
				
			||||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
					import androidx.compose.foundation.layout.fillMaxWidth
 | 
				
			||||||
import androidx.compose.foundation.layout.offset
 | 
					 | 
				
			||||||
import androidx.compose.foundation.layout.padding
 | 
					import androidx.compose.foundation.layout.padding
 | 
				
			||||||
import androidx.compose.foundation.layout.systemBarsPadding
 | 
					import androidx.compose.foundation.layout.statusBarsPadding
 | 
				
			||||||
import androidx.compose.foundation.rememberScrollState
 | 
					import androidx.compose.material.ExperimentalMaterialApi
 | 
				
			||||||
import androidx.compose.foundation.verticalScroll
 | 
					import androidx.compose.material.pullrefresh.PullRefreshState
 | 
				
			||||||
 | 
					import androidx.compose.material.pullrefresh.pullRefresh
 | 
				
			||||||
 | 
					import androidx.compose.material.pullrefresh.rememberPullRefreshState
 | 
				
			||||||
import androidx.compose.material3.Icon
 | 
					import androidx.compose.material3.Icon
 | 
				
			||||||
import androidx.compose.material3.IconButton
 | 
					import androidx.compose.material3.IconButton
 | 
				
			||||||
import androidx.compose.material3.MaterialTheme
 | 
					import androidx.compose.material3.MaterialTheme
 | 
				
			||||||
| 
						 | 
					@ -24,73 +20,33 @@ import androidx.compose.material3.Scaffold
 | 
				
			||||||
import androidx.compose.material3.Surface
 | 
					import androidx.compose.material3.Surface
 | 
				
			||||||
import androidx.compose.material3.Text
 | 
					import androidx.compose.material3.Text
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					 | 
				
			||||||
import androidx.compose.runtime.State
 | 
					 | 
				
			||||||
import androidx.compose.runtime.mutableStateOf
 | 
					 | 
				
			||||||
import androidx.compose.runtime.remember
 | 
					 | 
				
			||||||
import androidx.compose.ui.Alignment
 | 
					import androidx.compose.ui.Alignment
 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					import androidx.compose.ui.Modifier
 | 
				
			||||||
import androidx.compose.ui.graphics.Brush
 | 
					 | 
				
			||||||
import androidx.compose.ui.graphics.Color
 | 
					import androidx.compose.ui.graphics.Color
 | 
				
			||||||
import androidx.compose.ui.platform.LocalDensity
 | 
					 | 
				
			||||||
import androidx.compose.ui.res.painterResource
 | 
					import androidx.compose.ui.res.painterResource
 | 
				
			||||||
import androidx.compose.ui.res.stringResource
 | 
					import androidx.compose.ui.res.stringResource
 | 
				
			||||||
import androidx.compose.ui.tooling.preview.Preview
 | 
					import androidx.compose.ui.tooling.preview.Preview
 | 
				
			||||||
import androidx.compose.ui.unit.Density
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.IntOffset
 | 
					 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					import androidx.compose.ui.unit.dp
 | 
				
			||||||
import androidx.compose.ui.zIndex
 | 
					 | 
				
			||||||
import androidx.hilt.navigation.compose.hiltViewModel
 | 
					import androidx.hilt.navigation.compose.hiltViewModel
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.composable.KeepOnScreen
 | 
					import com.pixelized.rplexicon.ui.composable.KeepOnScreen
 | 
				
			||||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
 | 
					import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
 | 
				
			||||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet
 | 
					import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.AttributesSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.AttributesSummaryUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummaryPreview
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.CharacteristicsSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticViewModel
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.CharacteristicsSummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.PassivesSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.PassivesSummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.ProficiencySummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.ProficiencySummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.SavingThrowsSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.SavingThrowsSummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.SpellSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.SpellSummaryUio
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberCharacteristicsSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberClassHeaderSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberPassivesSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberProficienciesSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberSavingThrowsSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberSpellsSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberStatsSummary
 | 
					 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Stable
 | 
					@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
 | 
				
			||||||
data class SummaryUio(
 | 
					 | 
				
			||||||
    val headerVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val header: ClassHeaderSummaryUio,
 | 
					 | 
				
			||||||
    val statsVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val stats: AttributesSummaryUio,
 | 
					 | 
				
			||||||
    val characteristicsVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val characteristics: CharacteristicsSummaryUio,
 | 
					 | 
				
			||||||
    val savingThrowsVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val savingThrows: SavingThrowsSummaryUio,
 | 
					 | 
				
			||||||
    val proficienciesVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val proficiencies: ProficiencySummaryUio,
 | 
					 | 
				
			||||||
    val passivesVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val passives: PassivesSummaryUio,
 | 
					 | 
				
			||||||
    val spellsVisibility: State<Boolean>,
 | 
					 | 
				
			||||||
    val spells: SpellSummaryUio,
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
fun SummaryScreen(
 | 
					fun SummaryScreen(
 | 
				
			||||||
    viewModel: SummaryViewModel = hiltViewModel(),
 | 
					    statisticsViewModel: StatisticViewModel = hiltViewModel()
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    val screen = LocalScreenNavHost.current
 | 
					    val screen = LocalScreenNavHost.current
 | 
				
			||||||
 | 
					    val refresh = rememberPullRefreshState(
 | 
				
			||||||
 | 
					        refreshing = false,
 | 
				
			||||||
 | 
					        onRefresh = { },
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Surface(
 | 
					    Surface(
 | 
				
			||||||
        modifier = Modifier.fillMaxSize(),
 | 
					        modifier = Modifier.fillMaxSize(),
 | 
				
			||||||
| 
						 | 
					@ -98,27 +54,33 @@ fun SummaryScreen(
 | 
				
			||||||
        SummaryContent(
 | 
					        SummaryContent(
 | 
				
			||||||
            modifier = Modifier
 | 
					            modifier = Modifier
 | 
				
			||||||
                .fillMaxSize()
 | 
					                .fillMaxSize()
 | 
				
			||||||
                .systemBarsPadding(),
 | 
					                .statusBarsPadding(),
 | 
				
			||||||
            summary = viewModel.summary,
 | 
					            refreshState = refresh,
 | 
				
			||||||
            onBack = {
 | 
					            onBack = {
 | 
				
			||||||
                screen.popBackStack()
 | 
					                screen.popBackStack()
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            onHeader = {
 | 
					            statistics = {
 | 
				
			||||||
 | 
					                StatisticSummary(
 | 
				
			||||||
 | 
					                    summary = statisticsViewModel.summary,
 | 
				
			||||||
 | 
					                    onClass = {
 | 
				
			||||||
                        screen.navigateToCharacterSheet(name = it.label)
 | 
					                        screen.navigateToCharacterSheet(name = it.label)
 | 
				
			||||||
            }
 | 
					                    },
 | 
				
			||||||
 | 
					                    onDice = { },
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        KeepOnScreen()
 | 
					        KeepOnScreen()
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@OptIn(ExperimentalMaterialApi::class)
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
private fun SummaryContent(
 | 
					private fun SummaryContent(
 | 
				
			||||||
    modifier: Modifier = Modifier,
 | 
					    modifier: Modifier = Modifier,
 | 
				
			||||||
    scrollState: ScrollState = rememberScrollState(),
 | 
					    refreshState: PullRefreshState,
 | 
				
			||||||
    summary: SummaryUio,
 | 
					 | 
				
			||||||
    onBack: () -> Unit,
 | 
					    onBack: () -> Unit,
 | 
				
			||||||
    onHeader: (ClassHeaderSummaryUio.Header) -> Unit,
 | 
					    statistics: @Composable () -> Unit,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    Scaffold(
 | 
					    Scaffold(
 | 
				
			||||||
        modifier = modifier,
 | 
					        modifier = modifier,
 | 
				
			||||||
| 
						 | 
					@ -139,7 +101,7 @@ private fun SummaryContent(
 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                    Text(
 | 
					                    Text(
 | 
				
			||||||
                        text = stringResource(id = R.string.character_sheet_summary_title),
 | 
					                        text = stringResource(id = R.string.summary_title),
 | 
				
			||||||
                        style = MaterialTheme.typography.titleLarge,
 | 
					                        style = MaterialTheme.typography.titleLarge,
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
| 
						 | 
					@ -148,140 +110,26 @@ private fun SummaryContent(
 | 
				
			||||||
    ) { paddingValues ->
 | 
					    ) { paddingValues ->
 | 
				
			||||||
        Column(
 | 
					        Column(
 | 
				
			||||||
            modifier = Modifier
 | 
					            modifier = Modifier
 | 
				
			||||||
                .verticalScroll(state = scrollState)
 | 
					                .fillMaxSize()
 | 
				
			||||||
                .padding(paddingValues = paddingValues)
 | 
					                .pullRefresh(refreshState)
 | 
				
			||||||
                .padding(horizontal = 16.dp),
 | 
					                .padding(paddingValues = paddingValues),
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
            AnimatedVisibility(
 | 
					            statistics()
 | 
				
			||||||
                modifier = Modifier
 | 
					 | 
				
			||||||
                    .zIndex(zIndex = 1f)
 | 
					 | 
				
			||||||
                    .fillMaxWidth()
 | 
					 | 
				
			||||||
                    .offset { IntOffset(x = 0, y = scrollState.value) }
 | 
					 | 
				
			||||||
                    .background(brush = rememberHeaderBackgroundGradient())
 | 
					 | 
				
			||||||
                    .padding(bottom = 16.dp, end = 3.dp),
 | 
					 | 
				
			||||||
                visible = summary.headerVisibility.value,
 | 
					 | 
				
			||||||
                enter = fadeIn(),
 | 
					 | 
				
			||||||
            ) {
 | 
					 | 
				
			||||||
                ClassHeaderSummary(
 | 
					 | 
				
			||||||
                    header = summary.header,
 | 
					 | 
				
			||||||
                    onClick = onHeader,
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Column(
 | 
					 | 
				
			||||||
                verticalArrangement = Arrangement.spacedBy(space = 16.dp),
 | 
					 | 
				
			||||||
            ) {
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.statsVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    AttributesSummary(
 | 
					 | 
				
			||||||
                        attributes = summary.stats,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.characteristicsVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    CharacteristicsSummary(
 | 
					 | 
				
			||||||
                        characteristics = summary.characteristics,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.savingThrowsVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    SavingThrowsSummary(
 | 
					 | 
				
			||||||
                        savingThrows = summary.savingThrows,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.proficienciesVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    ProficiencySummary(
 | 
					 | 
				
			||||||
                        proficiencies = summary.proficiencies,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.passivesVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    PassivesSummary(
 | 
					 | 
				
			||||||
                        passives = summary.passives,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                AnimatedVisibility(
 | 
					 | 
				
			||||||
                    visible = summary.spellsVisibility.value,
 | 
					 | 
				
			||||||
                    enter = enterTransition(),
 | 
					 | 
				
			||||||
                ) {
 | 
					 | 
				
			||||||
                    SpellSummary(
 | 
					 | 
				
			||||||
                        spells = summary.spells,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@OptIn(ExperimentalMaterialApi::class)
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
private fun enterTransition(
 | 
					@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
 | 
				
			||||||
    density: Density = LocalDensity.current,
 | 
					@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
 | 
				
			||||||
): EnterTransition {
 | 
					 | 
				
			||||||
    return fadeIn() + slideInVertically { with(density) { 24.dp.roundToPx() } }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
private fun rememberHeaderBackgroundGradient(): Brush {
 | 
					 | 
				
			||||||
    val colorScheme = MaterialTheme.colorScheme
 | 
					 | 
				
			||||||
    return remember {
 | 
					 | 
				
			||||||
        Brush.verticalGradient(
 | 
					 | 
				
			||||||
            colors = listOf(
 | 
					 | 
				
			||||||
                colorScheme.surface.copy(alpha = 1.0f),
 | 
					 | 
				
			||||||
                colorScheme.surface.copy(alpha = 1.0f),
 | 
					 | 
				
			||||||
                colorScheme.surface.copy(alpha = 0.5f),
 | 
					 | 
				
			||||||
                colorScheme.surface.copy(alpha = 0.0f),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@Composable
 | 
					 | 
				
			||||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, heightDp = 1680)
 | 
					 | 
				
			||||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, heightDp = 1680)
 | 
					 | 
				
			||||||
private fun SummaryPreview() {
 | 
					private fun SummaryPreview() {
 | 
				
			||||||
    LexiconTheme {
 | 
					    LexiconTheme {
 | 
				
			||||||
        Surface {
 | 
					        Surface {
 | 
				
			||||||
            val header = rememberClassHeaderSummary()
 | 
					 | 
				
			||||||
            val stats = rememberStatsSummary()
 | 
					 | 
				
			||||||
            val characteristics = rememberCharacteristicsSummary()
 | 
					 | 
				
			||||||
            val savingThrows = rememberSavingThrowsSummary()
 | 
					 | 
				
			||||||
            val proficiencies = rememberProficienciesSummary()
 | 
					 | 
				
			||||||
            val passives = rememberPassivesSummary()
 | 
					 | 
				
			||||||
            val spells = rememberSpellsSummary()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            SummaryContent(
 | 
					            SummaryContent(
 | 
				
			||||||
                modifier = Modifier.fillMaxSize(),
 | 
					                refreshState = rememberPullRefreshState(refreshing = false, onRefresh = { }),
 | 
				
			||||||
                summary = remember {
 | 
					 | 
				
			||||||
                    SummaryUio(
 | 
					 | 
				
			||||||
                        headerVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        header = header,
 | 
					 | 
				
			||||||
                        statsVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        stats = stats,
 | 
					 | 
				
			||||||
                        characteristicsVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        characteristics = characteristics,
 | 
					 | 
				
			||||||
                        savingThrowsVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        savingThrows = savingThrows,
 | 
					 | 
				
			||||||
                        proficienciesVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        proficiencies = proficiencies,
 | 
					 | 
				
			||||||
                        passivesVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        passives = passives,
 | 
					 | 
				
			||||||
                        spellsVisibility = mutableStateOf(true),
 | 
					 | 
				
			||||||
                        spells = spells,
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                },
 | 
					 | 
				
			||||||
                onBack = { },
 | 
					                onBack = { },
 | 
				
			||||||
                onHeader = { },
 | 
					                statistics = { StatisticSummaryPreview() },
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberStatsSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberAttributesSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -78,7 +78,7 @@ private fun StatsSummaryPreview() {
 | 
				
			||||||
    LexiconTheme {
 | 
					    LexiconTheme {
 | 
				
			||||||
        Surface {
 | 
					        Surface {
 | 
				
			||||||
            AttributesSummary(
 | 
					            AttributesSummary(
 | 
				
			||||||
                attributes = rememberStatsSummary()
 | 
					                attributes = rememberAttributesSummary()
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberCharacteristicsSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberCharacteristicsSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,104 +2,208 @@ package com.pixelized.rplexicon.ui.screens.summary.composable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import android.content.res.Configuration
 | 
					import android.content.res.Configuration
 | 
				
			||||||
import androidx.annotation.DrawableRes
 | 
					import androidx.annotation.DrawableRes
 | 
				
			||||||
 | 
					import androidx.compose.animation.AnimatedContent
 | 
				
			||||||
 | 
					import androidx.compose.animation.AnimatedContentTransitionScope
 | 
				
			||||||
 | 
					import androidx.compose.animation.ContentTransform
 | 
				
			||||||
 | 
					import androidx.compose.animation.SizeTransform
 | 
				
			||||||
 | 
					import androidx.compose.animation.animateColorAsState
 | 
				
			||||||
 | 
					import androidx.compose.animation.core.tween
 | 
				
			||||||
 | 
					import androidx.compose.animation.fadeIn
 | 
				
			||||||
 | 
					import androidx.compose.animation.fadeOut
 | 
				
			||||||
 | 
					import androidx.compose.animation.slideInVertically
 | 
				
			||||||
 | 
					import androidx.compose.animation.slideOutVertically
 | 
				
			||||||
 | 
					import androidx.compose.animation.togetherWith
 | 
				
			||||||
import androidx.compose.foundation.layout.Arrangement
 | 
					import androidx.compose.foundation.layout.Arrangement
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Box
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Column
 | 
				
			||||||
import androidx.compose.foundation.layout.Row
 | 
					import androidx.compose.foundation.layout.Row
 | 
				
			||||||
import androidx.compose.foundation.layout.fillMaxWidth
 | 
					import androidx.compose.foundation.layout.fillMaxWidth
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.size
 | 
				
			||||||
import androidx.compose.foundation.layout.width
 | 
					import androidx.compose.foundation.layout.width
 | 
				
			||||||
import androidx.compose.material3.Icon
 | 
					import androidx.compose.material3.Icon
 | 
				
			||||||
import androidx.compose.material3.IconButton
 | 
					import androidx.compose.material3.IconButton
 | 
				
			||||||
import androidx.compose.material3.MaterialTheme
 | 
					import androidx.compose.material3.MaterialTheme
 | 
				
			||||||
import androidx.compose.material3.Surface
 | 
					import androidx.compose.material3.Surface
 | 
				
			||||||
 | 
					import androidx.compose.material3.Text
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.MutableState
 | 
					import androidx.compose.runtime.MutableState
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.State
 | 
				
			||||||
 | 
					import androidx.compose.runtime.derivedStateOf
 | 
				
			||||||
 | 
					import androidx.compose.runtime.remember
 | 
				
			||||||
import androidx.compose.ui.Alignment
 | 
					import androidx.compose.ui.Alignment
 | 
				
			||||||
import androidx.compose.ui.Modifier
 | 
					import androidx.compose.ui.Modifier
 | 
				
			||||||
 | 
					import androidx.compose.ui.geometry.Offset
 | 
				
			||||||
 | 
					import androidx.compose.ui.graphics.Color
 | 
				
			||||||
 | 
					import androidx.compose.ui.graphics.Shadow
 | 
				
			||||||
import androidx.compose.ui.res.painterResource
 | 
					import androidx.compose.ui.res.painterResource
 | 
				
			||||||
 | 
					import androidx.compose.ui.text.font.FontWeight
 | 
				
			||||||
 | 
					import androidx.compose.ui.text.style.TextAlign
 | 
				
			||||||
import androidx.compose.ui.tooling.preview.Preview
 | 
					import androidx.compose.ui.tooling.preview.Preview
 | 
				
			||||||
import androidx.compose.ui.unit.dp
 | 
					import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberClassHeaderSummary
 | 
					import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberClassHeaderSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
 | 
					import com.pixelized.rplexicon.utilitary.extentions.lexicon
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Stable
 | 
					@Stable
 | 
				
			||||||
data class ClassHeaderSummaryUio(
 | 
					data class ClassHeaderSummaryUio(
 | 
				
			||||||
    val c1: MutableState<Header>,
 | 
					    val clazz1: MutableState<Header>,
 | 
				
			||||||
    val c2: MutableState<Header>,
 | 
					    val dice1: MutableState<Dice>,
 | 
				
			||||||
    val c3: MutableState<Header>,
 | 
					    val clazz2: MutableState<Header>,
 | 
				
			||||||
    val c4: MutableState<Header>,
 | 
					    val dice2: MutableState<Dice>,
 | 
				
			||||||
    val c5: MutableState<Header>,
 | 
					    val clazz3: MutableState<Header>,
 | 
				
			||||||
 | 
					    val dice3: MutableState<Dice>,
 | 
				
			||||||
 | 
					    val clazz4: MutableState<Header>,
 | 
				
			||||||
 | 
					    val dice4: MutableState<Dice>,
 | 
				
			||||||
 | 
					    val clazz5: MutableState<Header>,
 | 
				
			||||||
 | 
					    val dice5: MutableState<Dice>,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
 | 
					    val classes = arrayListOf(clazz1, clazz2, clazz3, clazz4, clazz5)
 | 
				
			||||||
 | 
					    val dices = arrayListOf(dice1, dice2, dice3, dice4, dice5)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @Stable
 | 
					    @Stable
 | 
				
			||||||
    data class Header(
 | 
					    data class Header(
 | 
				
			||||||
        val label: String = "",
 | 
					        val label: String = "",
 | 
				
			||||||
        @DrawableRes val icon: Int = R.drawable.ic_d20_24,
 | 
					        @DrawableRes val icon: Int = R.drawable.ic_d20_24,
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @Stable
 | 
				
			||||||
 | 
					    data class Dice(
 | 
				
			||||||
 | 
					        val timestamp: Long = 0L,
 | 
				
			||||||
 | 
					        @DrawableRes val icon: Int = R.drawable.ic_d20_24,
 | 
				
			||||||
 | 
					        val isCriticalSuccess: Boolean = false,
 | 
				
			||||||
 | 
					        val isCriticalFailure: Boolean = false,
 | 
				
			||||||
 | 
					        val result: String = "",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
fun ClassHeaderSummary(
 | 
					fun ClassHeaderSummary(
 | 
				
			||||||
    modifier: Modifier = Modifier,
 | 
					    modifier: Modifier = Modifier,
 | 
				
			||||||
    header: ClassHeaderSummaryUio,
 | 
					    header: ClassHeaderSummaryUio,
 | 
				
			||||||
    onClick: (ClassHeaderSummaryUio.Header) -> Unit
 | 
					    onClass: (ClassHeaderSummaryUio.Header) -> Unit,
 | 
				
			||||||
 | 
					    onDice: (ClassHeaderSummaryUio.Dice) -> Unit,
 | 
				
			||||||
) {
 | 
					) {
 | 
				
			||||||
    Row(
 | 
					    Column(
 | 
				
			||||||
        modifier = modifier,
 | 
					        modifier = modifier,
 | 
				
			||||||
 | 
					        horizontalAlignment = Alignment.End,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        Row(
 | 
				
			||||||
 | 
					            horizontalArrangement = Arrangement.spacedBy(space = 1.dp),
 | 
				
			||||||
 | 
					            verticalAlignment = Alignment.CenterVertically,
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            header.classes.forEach {
 | 
				
			||||||
 | 
					                IconButton(
 | 
				
			||||||
 | 
					                    modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
				
			||||||
 | 
					                    onClick = { onClass(it.value) },
 | 
				
			||||||
 | 
					                ) {
 | 
				
			||||||
 | 
					                    Icon(
 | 
				
			||||||
 | 
					                        modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
				
			||||||
 | 
					                        painter = painterResource(id = it.value.icon),
 | 
				
			||||||
 | 
					                        contentDescription = null,
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        Row(
 | 
				
			||||||
            horizontalArrangement = Arrangement.spacedBy(space = 1.dp, alignment = Alignment.End),
 | 
					            horizontalArrangement = Arrangement.spacedBy(space = 1.dp, alignment = Alignment.End),
 | 
				
			||||||
            verticalAlignment = Alignment.CenterVertically,
 | 
					            verticalAlignment = Alignment.CenterVertically,
 | 
				
			||||||
        ) {
 | 
					        ) {
 | 
				
			||||||
        IconButton(
 | 
					            header.dices.forEach {
 | 
				
			||||||
            modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					                ClassHeaderDice(
 | 
				
			||||||
            onClick = { onClick(header.c1.value) },
 | 
					                    dice = it,
 | 
				
			||||||
        ) {
 | 
					                    onDice = onDice,
 | 
				
			||||||
            Icon(
 | 
					 | 
				
			||||||
                modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
                painter = painterResource(id = header.c1.value.icon),
 | 
					 | 
				
			||||||
                contentDescription = null,
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        IconButton(
 | 
					 | 
				
			||||||
            modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
            onClick = { onClick(header.c2.value) },
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            Icon(
 | 
					 | 
				
			||||||
                modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
                painter = painterResource(id = header.c2.value.icon),
 | 
					 | 
				
			||||||
                contentDescription = null,
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        IconButton(
 | 
					 | 
				
			||||||
            modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
            onClick = { onClick(header.c3.value) },
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            Icon(
 | 
					 | 
				
			||||||
                modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
                painter = painterResource(id = header.c3.value.icon),
 | 
					 | 
				
			||||||
                contentDescription = null,
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        IconButton(
 | 
					 | 
				
			||||||
            modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
            onClick = { onClick(header.c4.value) },
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            Icon(
 | 
					 | 
				
			||||||
                modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
                painter = painterResource(id = header.c4.value.icon),
 | 
					 | 
				
			||||||
                contentDescription = null,
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        IconButton(
 | 
					 | 
				
			||||||
            modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
            onClick = { onClick(header.c5.value) },
 | 
					 | 
				
			||||||
        ) {
 | 
					 | 
				
			||||||
            Icon(
 | 
					 | 
				
			||||||
                modifier = Modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
					 | 
				
			||||||
                painter = painterResource(id = header.c5.value.icon),
 | 
					 | 
				
			||||||
                contentDescription = null,
 | 
					 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					private fun ClassHeaderDice(
 | 
				
			||||||
 | 
					    modifier: Modifier = Modifier,
 | 
				
			||||||
 | 
					    dice: State<ClassHeaderSummaryUio.Dice>,
 | 
				
			||||||
 | 
					    onDice: (ClassHeaderSummaryUio.Dice) -> Unit
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    val typography = MaterialTheme.typography
 | 
				
			||||||
 | 
					    val colorScheme = MaterialTheme.colorScheme
 | 
				
			||||||
 | 
					    val style = remember {
 | 
				
			||||||
 | 
					        typography.headlineLarge.copy(
 | 
				
			||||||
 | 
					            shadow = Shadow(
 | 
				
			||||||
 | 
					                color = colorScheme.surface,
 | 
				
			||||||
 | 
					                offset = Offset.Zero,
 | 
				
			||||||
 | 
					                blurRadius = 10f,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    val textColor = animateColorAsState(
 | 
				
			||||||
 | 
					        targetValue = when {
 | 
				
			||||||
 | 
					            dice.value.isCriticalSuccess -> MaterialTheme.colorScheme.primary
 | 
				
			||||||
 | 
					            dice.value.isCriticalFailure -> Color.Red
 | 
				
			||||||
 | 
					            else -> MaterialTheme.colorScheme.onSurface
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        animationSpec = tween(
 | 
				
			||||||
 | 
					            delayMillis = RollDiceUio.ROLL_DURATION.toInt()
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					        label = "ClassHeaderDiceColorAnimation"
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    val iconColor = remember {
 | 
				
			||||||
 | 
					        derivedStateOf {
 | 
				
			||||||
 | 
					            textColor.value.copy(alpha = 0.5f)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Box(
 | 
				
			||||||
 | 
					        modifier = modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
				
			||||||
 | 
					        contentAlignment = Alignment.Center,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        IconButton(
 | 
				
			||||||
 | 
					            onClick = { onDice(dice.value) },
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            Icon(
 | 
				
			||||||
 | 
					                modifier = Modifier.size(MaterialTheme.lexicon.dimens.summary.cell),
 | 
				
			||||||
 | 
					                painter = painterResource(id = dice.value.icon),
 | 
				
			||||||
 | 
					                tint = iconColor.value,
 | 
				
			||||||
 | 
					                contentDescription = null,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        AnimatedContent(
 | 
				
			||||||
 | 
					            targetState = dice.value,
 | 
				
			||||||
 | 
					            label = "ClassHeaderDiceValueAnimation",
 | 
				
			||||||
 | 
					            transitionSpec = labelAnimationSpec()
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            Text(
 | 
				
			||||||
 | 
					                modifier = modifier.width(MaterialTheme.lexicon.dimens.summary.cell.width),
 | 
				
			||||||
 | 
					                style = style,
 | 
				
			||||||
 | 
					                textAlign = TextAlign.Center,
 | 
				
			||||||
 | 
					                fontWeight = FontWeight.Bold,
 | 
				
			||||||
 | 
					                color = textColor.value,
 | 
				
			||||||
 | 
					                text = it.result
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Stable
 | 
				
			||||||
 | 
					private fun labelAnimationSpec(): AnimatedContentTransitionScope<*>.() -> ContentTransform = {
 | 
				
			||||||
 | 
					    val slideIn = slideInVertically(
 | 
				
			||||||
 | 
					        animationSpec = tween(
 | 
				
			||||||
 | 
					            delayMillis = RollDiceUio.ROLL_DURATION.toInt()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    ) { it / 2 }
 | 
				
			||||||
 | 
					    val fadeIn = fadeIn(
 | 
				
			||||||
 | 
					        animationSpec = tween(
 | 
				
			||||||
 | 
					            delayMillis = RollDiceUio.ROLL_DURATION.toInt()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    val slideOut = slideOutVertically(
 | 
				
			||||||
 | 
					        animationSpec = tween()
 | 
				
			||||||
 | 
					    ) { -it / 2 }
 | 
				
			||||||
 | 
					    val fadeOut = fadeOut(
 | 
				
			||||||
 | 
					        animationSpec = tween()
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    slideIn + fadeIn togetherWith slideOut + fadeOut using SizeTransform(clip = false)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
| 
						 | 
					@ -111,7 +215,8 @@ private fun ClassHeaderSummaryPreview() {
 | 
				
			||||||
            ClassHeaderSummary(
 | 
					            ClassHeaderSummary(
 | 
				
			||||||
                modifier = Modifier.fillMaxWidth(),
 | 
					                modifier = Modifier.fillMaxWidth(),
 | 
				
			||||||
                header = rememberClassHeaderSummary(),
 | 
					                header = rememberClassHeaderSummary(),
 | 
				
			||||||
                onClick = { }
 | 
					                onClass = { },
 | 
				
			||||||
 | 
					                onDice = { },
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberPassivesSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberPassivesSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberProficienciesSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberProficienciesSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberSavingThrowsSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberSavingThrowsSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,7 +21,7 @@ import androidx.compose.ui.unit.dp
 | 
				
			||||||
import com.pixelized.rplexicon.R
 | 
					import com.pixelized.rplexicon.R
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRow
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.common.SummaryRowUio
 | 
				
			||||||
import com.pixelized.rplexicon.ui.screens.summary.composable.preview.rememberSpellsSummary
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberSpellsSummary
 | 
				
			||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
					import com.pixelized.rplexicon.utilitary.extentions.ddBorder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,7 +35,18 @@ data class SummaryRowUio(
 | 
				
			||||||
    val c3: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
					    val c3: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
				
			||||||
    val c4: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
					    val c4: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
				
			||||||
    val c5: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
					    val c5: MutableState<SummaryCellUio> = mutableStateOf(none()),
 | 
				
			||||||
)
 | 
					) {
 | 
				
			||||||
 | 
					    operator fun get(index: Int): MutableState<SummaryCellUio>? {
 | 
				
			||||||
 | 
					        return when (index) {
 | 
				
			||||||
 | 
					            0 -> c1
 | 
				
			||||||
 | 
					            1 -> c2
 | 
				
			||||||
 | 
					            2 -> c3
 | 
				
			||||||
 | 
					            3 -> c4
 | 
				
			||||||
 | 
					            4 -> c5
 | 
				
			||||||
 | 
					            else -> null
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
fun SummaryRow(
 | 
					fun SummaryRow(
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -11,7 +11,7 @@ import com.pixelized.rplexicon.ui.screens.summary.composable.common.label
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Composable
 | 
					@Composable
 | 
				
			||||||
@Stable
 | 
					@Stable
 | 
				
			||||||
fun rememberStatsSummary(): AttributesSummaryUio {
 | 
					fun rememberAttributesSummary(): AttributesSummaryUio {
 | 
				
			||||||
    return remember {
 | 
					    return remember {
 | 
				
			||||||
        AttributesSummaryUio(
 | 
					        AttributesSummaryUio(
 | 
				
			||||||
            hp = SummaryRowUio(
 | 
					            hp = SummaryRowUio(
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -12,36 +12,53 @@ import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryU
 | 
				
			||||||
fun rememberClassHeaderSummary(): ClassHeaderSummaryUio {
 | 
					fun rememberClassHeaderSummary(): ClassHeaderSummaryUio {
 | 
				
			||||||
    return remember {
 | 
					    return remember {
 | 
				
			||||||
        ClassHeaderSummaryUio(
 | 
					        ClassHeaderSummaryUio(
 | 
				
			||||||
            c1 = mutableStateOf(
 | 
					            clazz1 = mutableStateOf(
 | 
				
			||||||
                ClassHeaderSummaryUio.Header(
 | 
					                ClassHeaderSummaryUio.Header(
 | 
				
			||||||
                    label = "Brulkai",
 | 
					                    label = "Brulkai",
 | 
				
			||||||
                    icon = R.drawable.ic_class_barbarian_24,
 | 
					                    icon = R.drawable.ic_class_barbarian_24,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            c2 = mutableStateOf(
 | 
					            dice1 = mutableStateOf(
 | 
				
			||||||
 | 
					                ClassHeaderSummaryUio.Dice(
 | 
				
			||||||
 | 
					                    result = "20",
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            clazz2 = mutableStateOf(
 | 
				
			||||||
                ClassHeaderSummaryUio.Header(
 | 
					                ClassHeaderSummaryUio.Header(
 | 
				
			||||||
                    label = "Léandre",
 | 
					                    label = "Léandre",
 | 
				
			||||||
                    icon = R.drawable.ic_class_cleric_24,
 | 
					                    icon = R.drawable.ic_class_cleric_24,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            c3 = mutableStateOf(
 | 
					            dice2 = mutableStateOf(
 | 
				
			||||||
 | 
					                ClassHeaderSummaryUio.Dice()
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            clazz3 = mutableStateOf(
 | 
				
			||||||
                ClassHeaderSummaryUio.Header(
 | 
					                ClassHeaderSummaryUio.Header(
 | 
				
			||||||
                    label = "Nélia",
 | 
					                    label = "Nélia",
 | 
				
			||||||
                    icon = R.drawable.ic_class_ranger_24,
 | 
					                    icon = R.drawable.ic_class_ranger_24,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            c4 = mutableStateOf(
 | 
					            dice3 = mutableStateOf(
 | 
				
			||||||
 | 
					                ClassHeaderSummaryUio.Dice()
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            clazz4 = mutableStateOf(
 | 
				
			||||||
                ClassHeaderSummaryUio.Header(
 | 
					                ClassHeaderSummaryUio.Header(
 | 
				
			||||||
                    label = "Tigrane",
 | 
					                    label = "Tigrane",
 | 
				
			||||||
                    icon = R.drawable.ic_class_warlock_24,
 | 
					                    icon = R.drawable.ic_class_warlock_24,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
            c5 = mutableStateOf(
 | 
					            dice4 = mutableStateOf(
 | 
				
			||||||
 | 
					                ClassHeaderSummaryUio.Dice()
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					            clazz5 = mutableStateOf(
 | 
				
			||||||
                ClassHeaderSummaryUio.Header(
 | 
					                ClassHeaderSummaryUio.Header(
 | 
				
			||||||
                    label = "Unathana",
 | 
					                    label = "Unathana",
 | 
				
			||||||
                    icon = R.drawable.ic_class_bard_24,
 | 
					                    icon = R.drawable.ic_class_bard_24,
 | 
				
			||||||
                )
 | 
					                )
 | 
				
			||||||
            ),
 | 
					            ),
 | 
				
			||||||
 | 
					            dice5 = mutableStateOf(
 | 
				
			||||||
 | 
					                ClassHeaderSummaryUio.Dice()
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary.composable.preview
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.compose.runtime.Composable
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
import androidx.compose.runtime.Stable
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,38 @@
 | 
				
			||||||
 | 
					package com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.mutableStateOf
 | 
				
			||||||
 | 
					import androidx.compose.runtime.remember
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummaryUio
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					@Stable
 | 
				
			||||||
 | 
					fun rememberStatisticSummary(): StatisticSummaryUio {
 | 
				
			||||||
 | 
					    val header = rememberClassHeaderSummary()
 | 
				
			||||||
 | 
					    val attributes = rememberAttributesSummary()
 | 
				
			||||||
 | 
					    val characteristics = rememberCharacteristicsSummary()
 | 
				
			||||||
 | 
					    val savingThrows = rememberSavingThrowsSummary()
 | 
				
			||||||
 | 
					    val proficiencies = rememberProficienciesSummary()
 | 
				
			||||||
 | 
					    val passives = rememberPassivesSummary()
 | 
				
			||||||
 | 
					    val spells = rememberSpellsSummary()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return remember {
 | 
				
			||||||
 | 
					        StatisticSummaryUio(
 | 
				
			||||||
 | 
					            headerVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            header = header,
 | 
				
			||||||
 | 
					            statsVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            attributes = attributes,
 | 
				
			||||||
 | 
					            characteristicsVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            characteristics = characteristics,
 | 
				
			||||||
 | 
					            savingThrowsVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            savingThrows = savingThrows,
 | 
				
			||||||
 | 
					            proficienciesVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            proficiencies = proficiencies,
 | 
				
			||||||
 | 
					            passivesVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            passives = passives,
 | 
				
			||||||
 | 
					            spellsVisibility = mutableStateOf(true),
 | 
				
			||||||
 | 
					            spells = spells,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,189 @@
 | 
				
			||||||
 | 
					package com.pixelized.rplexicon.ui.screens.summary.pages.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import android.content.res.Configuration
 | 
				
			||||||
 | 
					import androidx.compose.animation.AnimatedVisibility
 | 
				
			||||||
 | 
					import androidx.compose.animation.EnterTransition
 | 
				
			||||||
 | 
					import androidx.compose.animation.fadeIn
 | 
				
			||||||
 | 
					import androidx.compose.animation.slideInVertically
 | 
				
			||||||
 | 
					import androidx.compose.foundation.ScrollState
 | 
				
			||||||
 | 
					import androidx.compose.foundation.background
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Arrangement
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.Column
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.fillMaxSize
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.fillMaxWidth
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.offset
 | 
				
			||||||
 | 
					import androidx.compose.foundation.layout.padding
 | 
				
			||||||
 | 
					import androidx.compose.foundation.rememberScrollState
 | 
				
			||||||
 | 
					import androidx.compose.foundation.verticalScroll
 | 
				
			||||||
 | 
					import androidx.compose.material3.MaterialTheme
 | 
				
			||||||
 | 
					import androidx.compose.material3.Surface
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Composable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.Stable
 | 
				
			||||||
 | 
					import androidx.compose.runtime.State
 | 
				
			||||||
 | 
					import androidx.compose.runtime.remember
 | 
				
			||||||
 | 
					import androidx.compose.ui.Modifier
 | 
				
			||||||
 | 
					import androidx.compose.ui.graphics.Brush
 | 
				
			||||||
 | 
					import androidx.compose.ui.platform.LocalDensity
 | 
				
			||||||
 | 
					import androidx.compose.ui.tooling.preview.Preview
 | 
				
			||||||
 | 
					import androidx.compose.ui.unit.Density
 | 
				
			||||||
 | 
					import androidx.compose.ui.unit.IntOffset
 | 
				
			||||||
 | 
					import androidx.compose.ui.unit.dp
 | 
				
			||||||
 | 
					import androidx.compose.ui.zIndex
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.AttributesSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.AttributesSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.CharacteristicsSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.CharacteristicsSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.PassivesSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.PassivesSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.ProficiencySummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.ProficiencySummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.SavingThrowsSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.SavingThrowsSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.SpellSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.SpellSummaryUio
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.composable.preview.statistic.rememberStatisticSummary
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.theme.LexiconTheme
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Stable
 | 
				
			||||||
 | 
					data class StatisticSummaryUio(
 | 
				
			||||||
 | 
					    val headerVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val header: ClassHeaderSummaryUio,
 | 
				
			||||||
 | 
					    val statsVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val attributes: AttributesSummaryUio,
 | 
				
			||||||
 | 
					    val characteristicsVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val characteristics: CharacteristicsSummaryUio,
 | 
				
			||||||
 | 
					    val savingThrowsVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val savingThrows: SavingThrowsSummaryUio,
 | 
				
			||||||
 | 
					    val proficienciesVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val proficiencies: ProficiencySummaryUio,
 | 
				
			||||||
 | 
					    val passivesVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val passives: PassivesSummaryUio,
 | 
				
			||||||
 | 
					    val spellsVisibility: State<Boolean>,
 | 
				
			||||||
 | 
					    val spells: SpellSummaryUio,
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					fun StatisticSummary(
 | 
				
			||||||
 | 
					    modifier: Modifier = Modifier,
 | 
				
			||||||
 | 
					    scrollState: ScrollState = rememberScrollState(),
 | 
				
			||||||
 | 
					    summary: StatisticSummaryUio,
 | 
				
			||||||
 | 
					    onClass: (ClassHeaderSummaryUio.Header) -> Unit,
 | 
				
			||||||
 | 
					    onDice: (ClassHeaderSummaryUio.Dice) -> Unit,
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    Column(
 | 
				
			||||||
 | 
					        modifier = Modifier
 | 
				
			||||||
 | 
					            .verticalScroll(state = scrollState)
 | 
				
			||||||
 | 
					            .padding(horizontal = 16.dp)
 | 
				
			||||||
 | 
					            .then(other = modifier),
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        AnimatedVisibility(
 | 
				
			||||||
 | 
					            modifier = Modifier
 | 
				
			||||||
 | 
					                .zIndex(zIndex = 1f)
 | 
				
			||||||
 | 
					                .fillMaxWidth()
 | 
				
			||||||
 | 
					                .offset { IntOffset(x = 0, y = scrollState.value) }
 | 
				
			||||||
 | 
					                .background(brush = rememberHeaderBackgroundGradient())
 | 
				
			||||||
 | 
					                .padding(bottom = 16.dp, end = 3.dp),
 | 
				
			||||||
 | 
					            visible = summary.headerVisibility.value,
 | 
				
			||||||
 | 
					            enter = fadeIn(),
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            ClassHeaderSummary(
 | 
				
			||||||
 | 
					                header = summary.header,
 | 
				
			||||||
 | 
					                onClass = onClass,
 | 
				
			||||||
 | 
					                onDice = onDice,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Column(
 | 
				
			||||||
 | 
					            verticalArrangement = Arrangement.spacedBy(space = 16.dp),
 | 
				
			||||||
 | 
					        ) {
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.statsVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                AttributesSummary(
 | 
				
			||||||
 | 
					                    attributes = summary.attributes,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.characteristicsVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                CharacteristicsSummary(
 | 
				
			||||||
 | 
					                    characteristics = summary.characteristics,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.savingThrowsVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                SavingThrowsSummary(
 | 
				
			||||||
 | 
					                    savingThrows = summary.savingThrows,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.proficienciesVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                ProficiencySummary(
 | 
				
			||||||
 | 
					                    proficiencies = summary.proficiencies,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.passivesVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                PassivesSummary(
 | 
				
			||||||
 | 
					                    passives = summary.passives,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            AnimatedVisibility(
 | 
				
			||||||
 | 
					                visible = summary.spellsVisibility.value,
 | 
				
			||||||
 | 
					                enter = enterTransition(),
 | 
				
			||||||
 | 
					            ) {
 | 
				
			||||||
 | 
					                SpellSummary(
 | 
				
			||||||
 | 
					                    spells = summary.spells,
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					private fun enterTransition(
 | 
				
			||||||
 | 
					    density: Density = LocalDensity.current,
 | 
				
			||||||
 | 
					): EnterTransition {
 | 
				
			||||||
 | 
					    return fadeIn() + slideInVertically { with(density) { 24.dp.roundToPx() } }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					private fun rememberHeaderBackgroundGradient(): Brush {
 | 
				
			||||||
 | 
					    val colorScheme = MaterialTheme.colorScheme
 | 
				
			||||||
 | 
					    return remember {
 | 
				
			||||||
 | 
					        Brush.verticalGradient(
 | 
				
			||||||
 | 
					            colors = listOf(
 | 
				
			||||||
 | 
					                colorScheme.surface.copy(alpha = 1.0f),
 | 
				
			||||||
 | 
					                colorScheme.surface.copy(alpha = 1.0f),
 | 
				
			||||||
 | 
					                colorScheme.surface.copy(alpha = 0.75f),
 | 
				
			||||||
 | 
					                colorScheme.surface.copy(alpha = 0.0f),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Composable
 | 
				
			||||||
 | 
					@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO, heightDp = 1680)
 | 
				
			||||||
 | 
					@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES, heightDp = 1680)
 | 
				
			||||||
 | 
					fun StatisticSummaryPreview() {
 | 
				
			||||||
 | 
					    LexiconTheme {
 | 
				
			||||||
 | 
					        Surface {
 | 
				
			||||||
 | 
					            StatisticSummary(
 | 
				
			||||||
 | 
					                modifier = Modifier.fillMaxSize(),
 | 
				
			||||||
 | 
					                summary = rememberStatisticSummary(),
 | 
				
			||||||
 | 
					                onClass = { },
 | 
				
			||||||
 | 
					                onDice = { },
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,12 +1,13 @@
 | 
				
			||||||
package com.pixelized.rplexicon.ui.screens.summary
 | 
					package com.pixelized.rplexicon.ui.screens.summary.pages.statistic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import androidx.lifecycle.ViewModel
 | 
					import androidx.lifecycle.ViewModel
 | 
				
			||||||
import androidx.lifecycle.viewModelScope
 | 
					import androidx.lifecycle.viewModelScope
 | 
				
			||||||
 | 
					import com.pixelized.rplexicon.ui.screens.summary.SummaryFactory
 | 
				
			||||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
					import dagger.hilt.android.lifecycle.HiltViewModel
 | 
				
			||||||
import javax.inject.Inject
 | 
					import javax.inject.Inject
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@HiltViewModel
 | 
					@HiltViewModel
 | 
				
			||||||
class SummaryViewModel @Inject constructor(
 | 
					class StatisticViewModel @Inject constructor(
 | 
				
			||||||
    factory: SummaryFactory,
 | 
					    factory: SummaryFactory,
 | 
				
			||||||
) : ViewModel() {
 | 
					) : ViewModel() {
 | 
				
			||||||
    val summary = factory.fetchSummary(viewModelScope)
 | 
					    val summary = factory.fetchSummary(viewModelScope)
 | 
				
			||||||
| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
package com.pixelized.rplexicon.utilitary.extentions.local
 | 
					package com.pixelized.rplexicon.utilitary.extentions.local
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
					import com.pixelized.rplexicon.data.model.CharacterSheet
 | 
				
			||||||
import com.pixelized.rplexicon.data.model.CharacterSheetFire
 | 
					import com.pixelized.rplexicon.data.network.CharacterSheetFire
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fun CharacterSheet.spell(level: Int): Int? = when (level) {
 | 
					fun CharacterSheet.spell(level: Int): Int? = when (level) {
 | 
				
			||||||
    1 -> spell1
 | 
					    1 -> spell1
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,6 @@
 | 
				
			||||||
    <string name="map_destination">Destinations :</string>
 | 
					    <string name="map_destination">Destinations :</string>
 | 
				
			||||||
    <string name="map_illustrations">Illustrations :</string>
 | 
					    <string name="map_illustrations">Illustrations :</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <string name="character_sheet_summary_title">Détails des personnages</string>
 | 
					 | 
				
			||||||
    <string name="character_sheet_refresh_label">Rafraichir</string>
 | 
					    <string name="character_sheet_refresh_label">Rafraichir</string>
 | 
				
			||||||
    <string name="character_sheet_tab_proficiency">Talents</string>
 | 
					    <string name="character_sheet_tab_proficiency">Talents</string>
 | 
				
			||||||
    <string name="character_sheet_tab_inventory">Inventaire</string>
 | 
					    <string name="character_sheet_tab_inventory">Inventaire</string>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,7 +86,6 @@
 | 
				
			||||||
    <string name="map_destination">Destinations:</string>
 | 
					    <string name="map_destination">Destinations:</string>
 | 
				
			||||||
    <string name="map_illustrations">Illustrations:</string>
 | 
					    <string name="map_illustrations">Illustrations:</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <string name="character_sheet_summary_title">Characters sheets details</string>
 | 
					 | 
				
			||||||
    <string name="character_sheet_refresh_label">Refresh</string>
 | 
					    <string name="character_sheet_refresh_label">Refresh</string>
 | 
				
			||||||
    <string name="character_sheet_tab_proficiency">Proficiencies</string>
 | 
					    <string name="character_sheet_tab_proficiency">Proficiencies</string>
 | 
				
			||||||
    <string name="character_sheet_tab_inventory">Inventory</string>
 | 
					    <string name="character_sheet_tab_inventory">Inventory</string>
 | 
				
			||||||
| 
						 | 
					@ -216,4 +215,9 @@
 | 
				
			||||||
    <string name="character_sheet_equipment_main_hand">Main hand</string>
 | 
					    <string name="character_sheet_equipment_main_hand">Main hand</string>
 | 
				
			||||||
    <string name="character_sheet_equipment_off_hand">Off hand</string>
 | 
					    <string name="character_sheet_equipment_off_hand">Off hand</string>
 | 
				
			||||||
    <string name="character_sheet_equipment_empty_description">This equipment does not have any description</string>
 | 
					    <string name="character_sheet_equipment_empty_description">This equipment does not have any description</string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    <string name="summary_title">Game Master</string>
 | 
				
			||||||
 | 
					    <string name="summary_title_tab_statistics">Statistic</string>
 | 
				
			||||||
 | 
					    <string name="summary_title_tab_combats">Combat</string>
 | 
				
			||||||
 | 
					    <string name="summary_title_tab_rolls">Rolls</string>
 | 
				
			||||||
</resources>
 | 
					</resources>
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue