Add detail on shared throws
This commit is contained in:
parent
980a7e7929
commit
ff88c99342
10 changed files with 275 additions and 138 deletions
|
|
@ -11,7 +11,6 @@ import com.pixelized.rplexicon.data.model.Property
|
|||
import com.pixelized.rplexicon.data.model.Skill
|
||||
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.AlterationRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||
|
|
@ -19,7 +18,6 @@ import com.pixelized.rplexicon.data.repository.character.ObjectActionRepository
|
|||
import com.pixelized.rplexicon.data.repository.character.SkillRepository
|
||||
import com.pixelized.rplexicon.data.repository.character.SpellRepository
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||
import com.pixelized.rplexicon.utilitary.extentions.icon
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.advantage
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.critical
|
||||
|
|
@ -39,8 +37,7 @@ import kotlin.math.min
|
|||
|
||||
data class DiceThrowResult(
|
||||
val dice: RollDiceUio,
|
||||
val card: ThrowsCardUio,
|
||||
val network: NetworkThrow,
|
||||
val throws: NetworkThrow,
|
||||
)
|
||||
|
||||
@Suppress("KotlinConstantConditions")
|
||||
|
|
@ -579,7 +576,7 @@ class DiceThrowUseCase @Inject constructor(
|
|||
if (relatedTitleString != null) {
|
||||
allValue.add(value)
|
||||
listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = relatedTitleString,
|
||||
result = "$value",
|
||||
)
|
||||
|
|
@ -621,7 +618,7 @@ class DiceThrowUseCase @Inject constructor(
|
|||
val mastery = character.proficiency * multiplier
|
||||
allValue.add(mastery)
|
||||
listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = application.getString(
|
||||
when (multiplier) {
|
||||
2 -> R.string.dice_roll_expertise_bonus
|
||||
|
|
@ -646,18 +643,19 @@ class DiceThrowUseCase @Inject constructor(
|
|||
isCriticalFailure = result.value == 1,
|
||||
result = rollResult,
|
||||
),
|
||||
card = ThrowsCardUio(
|
||||
throws = NetworkThrow(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
title = abilityTitleString.uppercase(),
|
||||
highlight = abilityLabelString.uppercase(),
|
||||
dice = R.drawable.ic_d20_24,
|
||||
face = 20,
|
||||
roll = allValue.toLabel(),
|
||||
result = rollResult,
|
||||
isCriticalSuccess = result.value == 20,
|
||||
isCriticalFailure = result.value == 1,
|
||||
details = listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = abilityTitleString,
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = R.drawable.ic_d20_24,
|
||||
advantage = advantage,
|
||||
disadvantage = disadvantage,
|
||||
|
|
@ -668,18 +666,6 @@ class DiceThrowUseCase @Inject constructor(
|
|||
),
|
||||
) + 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()
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -743,7 +729,7 @@ class DiceThrowUseCase @Inject constructor(
|
|||
val flatBonus = diceThrow?.flat?.takeIf { it > 0 }?.let {
|
||||
allValue.add(it)
|
||||
listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = application.getString(R.string.dice_roll_bonus_detail, action),
|
||||
result = "$it",
|
||||
)
|
||||
|
|
@ -765,18 +751,19 @@ class DiceThrowUseCase @Inject constructor(
|
|||
isCriticalFailure = canMakeCriticalRoll && result.value == 1,
|
||||
result = rollResult,
|
||||
),
|
||||
card = ThrowsCardUio(
|
||||
throws = NetworkThrow(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
title = titleString.uppercase(),
|
||||
highlight = action,
|
||||
dice = diceThrow?.faces?.icon ?: R.drawable.ic_d20_24,
|
||||
highlight = action.uppercase(),
|
||||
face = diceThrow?.faces ?: 20,
|
||||
isCriticalSuccess = canMakeCriticalRoll && result.value == 20,
|
||||
isCriticalFailure = canMakeCriticalRoll && result.value == 1,
|
||||
roll = allValue.toLabel(),
|
||||
result = rollResult,
|
||||
details = listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = action,
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = diceThrow?.faces?.icon ?: R.drawable.ic_d20_24,
|
||||
advantage = advantage,
|
||||
disadvantage = disadvantage,
|
||||
|
|
@ -787,18 +774,6 @@ class DiceThrowUseCase @Inject constructor(
|
|||
),
|
||||
) + 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()
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -837,9 +812,9 @@ class DiceThrowUseCase @Inject constructor(
|
|||
fail = status[Property.SPELL_EFFECT].fail,
|
||||
critical = status[Property.SPELL_EFFECT].critical,
|
||||
)
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = application.getString(R.string.spell_level_chooser_label, "$it"),
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = spell.level.faces.icon,
|
||||
roll = "${spell.level.amount}d${spell.level.faces}",
|
||||
advantage = advantage,
|
||||
|
|
@ -865,16 +840,17 @@ class DiceThrowUseCase @Inject constructor(
|
|||
icon = (spell?.effect?.faces ?: 4).icon,
|
||||
result = rollResult,
|
||||
),
|
||||
card = ThrowsCardUio(
|
||||
throws = NetworkThrow(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
title = titleString.uppercase(),
|
||||
highlight = spellName,
|
||||
dice = (spell?.effect?.faces ?: 4).icon,
|
||||
highlight = spellName.uppercase(),
|
||||
face = spell?.effect?.faces ?: 4,
|
||||
roll = allValue.toLabel(),
|
||||
result = rollResult,
|
||||
details = listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = spellName,
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = (spell?.effect?.faces ?: 4).icon,
|
||||
roll = "${spell?.effect?.amount ?: 1}d${spell?.effect?.faces ?: 4}",
|
||||
advantage = advantage,
|
||||
|
|
@ -885,16 +861,6 @@ class DiceThrowUseCase @Inject constructor(
|
|||
),
|
||||
) + 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()
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -939,16 +905,17 @@ class DiceThrowUseCase @Inject constructor(
|
|||
icon = (skill?.effect?.faces ?: 4).icon,
|
||||
result = rollResult,
|
||||
),
|
||||
card = ThrowsCardUio(
|
||||
throws = NetworkThrow(
|
||||
timestamp = System.currentTimeMillis(),
|
||||
title = titleString.uppercase(),
|
||||
highlight = spellName ?: "",
|
||||
dice = (skill?.effect?.faces ?: 4).icon,
|
||||
highlight = spellName?.uppercase() ?: "",
|
||||
face = skill?.effect?.faces ?: 4,
|
||||
roll = allValue.toLabel(),
|
||||
result = rollResult,
|
||||
details = listOf(
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = spellName ?: "",
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = (skill?.effect?.faces ?: 4).icon,
|
||||
roll = "${skill?.effect?.amount ?: 1}d${skill?.effect?.faces ?: 4}",
|
||||
advantage = advantage,
|
||||
|
|
@ -959,26 +926,10 @@ class DiceThrowUseCase @Inject constructor(
|
|||
),
|
||||
) + 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.
|
||||
*/
|
||||
|
|
@ -993,11 +944,11 @@ class DiceThrowUseCase @Inject constructor(
|
|||
/**
|
||||
* Fetch any stats / proficiency / level related bonus and build a ThrowsCardUio.Detail for each.
|
||||
*/
|
||||
fun Throw?.statBonus(name: String?): List<ThrowsCardUio.Detail> {
|
||||
fun Throw?.statBonus(name: String?): List<NetworkThrow.Detail> {
|
||||
return this?.modifier?.mapNotNull { it.statBonus(name = name) } ?: emptyList()
|
||||
}
|
||||
|
||||
fun Property.statBonus(name: String?): ThrowsCardUio.Detail? {
|
||||
fun Property.statBonus(name: String?): NetworkThrow.Detail? {
|
||||
return when (this) {
|
||||
Property.STRENGTH -> (character.strength + this@ThrowScope.status[this].sum).modifier
|
||||
Property.DEXTERITY -> (character.dexterity + this@ThrowScope.status[this].sum).modifier
|
||||
|
|
@ -1025,7 +976,7 @@ class DiceThrowUseCase @Inject constructor(
|
|||
context.getString(R.string.dice_roll_bonus_detail, label)
|
||||
}
|
||||
allValue.add(value)
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = titleLabel,
|
||||
result = "$value",
|
||||
)
|
||||
|
|
@ -1035,7 +986,7 @@ class DiceThrowUseCase @Inject constructor(
|
|||
/**
|
||||
* Fetch any alteration related bonus and build a ThrowsCardUio.Detail for each.
|
||||
*/
|
||||
fun List<Alteration.Status>?.alterationsBonus(): List<ThrowsCardUio.Detail> {
|
||||
fun List<Alteration.Status>?.alterationsBonus(): List<NetworkThrow.Detail> {
|
||||
return this?.flatMap { status ->
|
||||
status.dices.map { dice ->
|
||||
val localRoll = roll(
|
||||
|
|
@ -1046,9 +997,9 @@ class DiceThrowUseCase @Inject constructor(
|
|||
fail = status.fail,
|
||||
critical = status.critical,
|
||||
)
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = dice.title ?: "",
|
||||
throws = ThrowsCardUio.Throw(
|
||||
throws = NetworkThrow.Throw(
|
||||
dice = dice.faces.icon,
|
||||
advantage = dice.advantage,
|
||||
disadvantage = dice.disadvantage,
|
||||
|
|
@ -1064,11 +1015,11 @@ class DiceThrowUseCase @Inject constructor(
|
|||
/**
|
||||
* Fetch any flat number related bonus and build a ThrowsCardUio.Detail for each.
|
||||
*/
|
||||
fun List<Alteration.Status>?.flatAlterationBonus(): List<ThrowsCardUio.Detail> {
|
||||
fun List<Alteration.Status>?.flatAlterationBonus(): List<NetworkThrow.Detail> {
|
||||
return this?.flatMap { status ->
|
||||
status.bonus.map { bonus ->
|
||||
allValue.add(bonus.value)
|
||||
ThrowsCardUio.Detail(
|
||||
NetworkThrow.Detail(
|
||||
title = bonus.title,
|
||||
result = "${bonus.value}",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,18 @@ data class NetworkThrow(
|
|||
@set:PropertyName(TITLE)
|
||||
var title: String = "",
|
||||
|
||||
@get:PropertyName(HIGHLIGHT)
|
||||
@set:PropertyName(HIGHLIGHT)
|
||||
var highlight: String = "",
|
||||
|
||||
@get:PropertyName(FACE)
|
||||
@set:PropertyName(FACE)
|
||||
var face: Int = 20,
|
||||
|
||||
@get:PropertyName(ROLL)
|
||||
@set:PropertyName(ROLL)
|
||||
var roll: String = "",
|
||||
|
||||
@get:PropertyName(RESULT)
|
||||
@set:PropertyName(RESULT)
|
||||
var result: String = "",
|
||||
|
|
@ -29,26 +41,58 @@ data class NetworkThrow(
|
|||
|
||||
@get:PropertyName(DETAILS)
|
||||
@set:PropertyName(DETAILS)
|
||||
var details: List<Bonus> = emptyList(),
|
||||
var details: List<Detail> = emptyList(),
|
||||
) {
|
||||
@Keep
|
||||
@IgnoreExtraProperties
|
||||
data class Bonus(
|
||||
@get:PropertyName(LABEL)
|
||||
@set:PropertyName(LABEL)
|
||||
var label: String = "",
|
||||
data class Detail(
|
||||
@get:PropertyName(TITLE)
|
||||
@set:PropertyName(TITLE)
|
||||
var title: String = "",
|
||||
|
||||
@get:PropertyName(RESULT)
|
||||
@set:PropertyName(RESULT)
|
||||
var result: String = "",
|
||||
|
||||
@get:PropertyName(THROW)
|
||||
@set:PropertyName(THROW)
|
||||
var throws: Throw? = null,
|
||||
) {
|
||||
companion object {
|
||||
const val TITLE = "title"
|
||||
const val RESULT = "result"
|
||||
const val THROW = "throw"
|
||||
}
|
||||
}
|
||||
|
||||
@Keep
|
||||
@IgnoreExtraProperties
|
||||
data class Throw(
|
||||
@get:PropertyName(DICE)
|
||||
@set:PropertyName(DICE)
|
||||
var dice: String? = null,
|
||||
var dice: Int = 20,
|
||||
|
||||
@get:PropertyName(ADVANTAGE)
|
||||
@set:PropertyName(ADVANTAGE)
|
||||
var advantage: Boolean? = null,
|
||||
|
||||
@get:PropertyName(DISADVANTAGE)
|
||||
@set:PropertyName(DISADVANTAGE)
|
||||
var disadvantage: Boolean? = null,
|
||||
|
||||
@get:PropertyName(ROLL)
|
||||
@set:PropertyName(ROLL)
|
||||
var roll: String = "",
|
||||
|
||||
@get:PropertyName(RESULT)
|
||||
@set:PropertyName(RESULT)
|
||||
var result: String = "",
|
||||
) {
|
||||
companion object {
|
||||
const val LABEL = "label"
|
||||
const val DICE = "dice"
|
||||
const val ADVANTAGE = "adv"
|
||||
const val DISADVANTAGE = "dis"
|
||||
const val ROLL = "roll"
|
||||
const val RESULT = "result"
|
||||
}
|
||||
}
|
||||
|
|
@ -56,6 +100,9 @@ data class NetworkThrow(
|
|||
companion object {
|
||||
const val TIMESTAMP = "timestamp"
|
||||
const val TITLE = "title"
|
||||
const val HIGHLIGHT = "highlight"
|
||||
const val FACE = "face"
|
||||
const val ROLL = "roll"
|
||||
const val RESULT = "result"
|
||||
const val CRITICAL = "crit"
|
||||
const val FAIL = "fail"
|
||||
|
|
|
|||
|
|
@ -170,13 +170,6 @@ class FirebaseRepository @Inject constructor(
|
|||
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
|
||||
|
|
@ -207,6 +200,13 @@ class FirebaseRepository @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
fun sendThrow(character: String?, throws: NetworkThrow) {
|
||||
character?.let {
|
||||
val reference = database.getReference("$PATH_THROWS/")
|
||||
reference.updateChildren(mapOf(it to throws))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val TAG = "FirebaseRepository"
|
||||
private const val PATH_CHARACTERS = "Characters"
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import com.pixelized.rplexicon.ui.screens.character.composable.actions.Alteratio
|
|||
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationDetailUio
|
||||
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationGroupUio
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.factory.AlterationFactory
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.factory.DiceFactory
|
||||
|
|
@ -38,6 +39,7 @@ class RollOverlayViewModel @Inject constructor(
|
|||
private val diceFactory: DiceFactory,
|
||||
private val alterationFactory: AlterationFactory,
|
||||
private val firebaseRepository: FirebaseRepository,
|
||||
private val throwCardFactory: ThrowCardFactory,
|
||||
application: Application,
|
||||
) : AndroidViewModel(application) {
|
||||
private var sheet: CharacterSheet? = null
|
||||
|
|
@ -63,7 +65,7 @@ class RollOverlayViewModel @Inject constructor(
|
|||
private val _card = mutableStateOf<ThrowsCardUio?>(null)
|
||||
val card: State<ThrowsCardUio?> get() = _card
|
||||
|
||||
private val _showDetail = mutableStateOf(false)
|
||||
private val _showDetail = mutableStateOf(true)
|
||||
val showDetail: State<Boolean> get() = _showDetail
|
||||
|
||||
private val _alterationDetail = mutableStateOf<AlterationDetailUio?>(null)
|
||||
|
|
@ -96,7 +98,7 @@ class RollOverlayViewModel @Inject constructor(
|
|||
alterationId = _alterations.value.mapNotNull { if (it.checked) it.label else null },
|
||||
)
|
||||
// share the result
|
||||
result?.network?.let {
|
||||
result?.throws?.let {
|
||||
firebaseRepository.sendThrow(sheet?.name, it)
|
||||
}
|
||||
// Start the roll animation.
|
||||
|
|
@ -112,7 +114,7 @@ class RollOverlayViewModel @Inject constructor(
|
|||
result?.dice?.let { _dice.value = it }
|
||||
delay(250)
|
||||
// Display the roll card.
|
||||
result?.card?.let { _card.value = it }
|
||||
result?.throws?.let { _card.value = throwCardFactory.convert(it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
package com.pixelized.rplexicon.ui.screens.rolls.composable
|
||||
|
||||
import com.pixelized.rplexicon.data.network.NetworkThrow
|
||||
import com.pixelized.rplexicon.utilitary.extentions.icon
|
||||
import javax.inject.Inject
|
||||
|
||||
class ThrowCardFactory @Inject constructor() {
|
||||
|
||||
fun convert(throws: NetworkThrow): ThrowsCardUio {
|
||||
return ThrowsCardUio(
|
||||
id = "${throws.timestamp}",
|
||||
title = throws.title,
|
||||
highlight = throws.highlight,
|
||||
dice = throws.face.icon,
|
||||
roll = throws.roll,
|
||||
result = throws.result,
|
||||
isCriticalSuccess = throws.isCriticalSuccess == true,
|
||||
isCriticalFailure = throws.isCriticalFailure == true,
|
||||
details = throws.details.map { detail ->
|
||||
ThrowsCardUio.Detail(
|
||||
title = detail.title,
|
||||
result = detail.result,
|
||||
throws = detail.throws?.let { dice ->
|
||||
ThrowsCardUio.Throw(
|
||||
dice = dice.dice.icon,
|
||||
advantage = dice.advantage == true,
|
||||
disadvantage = dice.disadvantage == true,
|
||||
roll = dice.roll,
|
||||
result = dice.result,
|
||||
)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -55,7 +55,7 @@ import java.util.UUID
|
|||
@Stable
|
||||
data class ThrowsCardUio(
|
||||
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
|
||||
@DrawableRes val dice: Int?, // the dice icon
|
||||
val roll: String, // the roll + bonus string.
|
||||
|
|
@ -66,7 +66,7 @@ data class ThrowsCardUio(
|
|||
) {
|
||||
@Stable
|
||||
data class Detail(
|
||||
val title: String = "", // the detail title
|
||||
val title: String = "", // the detail title
|
||||
val throws: Throw? = null, // the detail of the roll if any
|
||||
val result: String, // the result
|
||||
)
|
||||
|
|
@ -114,8 +114,10 @@ fun ThrowsCard(
|
|||
.padding(all = 16.dp)
|
||||
.animateContentSize(),
|
||||
) {
|
||||
throws.title?.let {
|
||||
val highlightRegex = remember(it) { highlightRegex(term = it) }
|
||||
throws.title.let {
|
||||
val highlightRegex = remember(throws.highlight) {
|
||||
highlightRegex(term = throws.highlight ?: it)
|
||||
}
|
||||
Text(
|
||||
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.65f),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
|
|
@ -202,7 +204,7 @@ private fun ThrowsRollDetail(
|
|||
modifier = modifier,
|
||||
horizontalArrangement = Arrangement.spacedBy(space = 4.dp),
|
||||
) {
|
||||
detail.title?.let {
|
||||
detail.title.let {
|
||||
Text(
|
||||
modifier = Modifier.alignByBaseline(),
|
||||
color = MaterialTheme.colorScheme.onSurface,
|
||||
|
|
@ -312,8 +314,8 @@ private class RollToastPreviewProvider : PreviewParameterProvider<ThrowsCardUio>
|
|||
),
|
||||
),
|
||||
ThrowsCardUio(
|
||||
title = "ATTACK HIT",
|
||||
highlight = "HIT",
|
||||
title = "JET D'ATTAQUE : \"HACHE DE GUERRE\"",
|
||||
highlight = "Hache de guerre",
|
||||
dice = R.drawable.ic_d20_24,
|
||||
roll = "20 + 2 + 3 + 2",
|
||||
result = "20",
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package com.pixelized.rplexicon.ui.screens.summary
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.fadeIn
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.animation.togetherWith
|
||||
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.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.navigationBarsPadding
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.material.ExperimentalMaterialApi
|
||||
|
|
@ -20,6 +25,9 @@ import androidx.compose.material3.Scaffold
|
|||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
|
|
@ -27,17 +35,21 @@ import androidx.compose.ui.res.painterResource
|
|||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.Dialog
|
||||
import androidx.compose.ui.window.DialogProperties
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import com.pixelized.rplexicon.R
|
||||
import com.pixelized.rplexicon.ui.composable.KeepOnScreen
|
||||
import com.pixelized.rplexicon.ui.navigation.LocalScreenNavHost
|
||||
import com.pixelized.rplexicon.ui.navigation.screens.navigateToCharacterSheet
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||
import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummary
|
||||
import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticSummaryPreview
|
||||
import com.pixelized.rplexicon.ui.screens.summary.pages.statistic.StatisticViewModel
|
||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class, ExperimentalFoundationApi::class)
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun SummaryScreen(
|
||||
statisticsViewModel: StatisticViewModel = hiltViewModel()
|
||||
|
|
@ -51,29 +63,75 @@ fun SummaryScreen(
|
|||
Surface(
|
||||
modifier = Modifier.fillMaxSize(),
|
||||
) {
|
||||
SummaryContent(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.statusBarsPadding(),
|
||||
refreshState = refresh,
|
||||
onBack = {
|
||||
screen.popBackStack()
|
||||
},
|
||||
statistics = {
|
||||
StatisticSummary(
|
||||
summary = statisticsViewModel.summary,
|
||||
onClass = {
|
||||
screen.navigateToCharacterSheet(name = it.label)
|
||||
},
|
||||
onDice = { },
|
||||
)
|
||||
},
|
||||
)
|
||||
Box {
|
||||
SummaryContent(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.statusBarsPadding(),
|
||||
refreshState = refresh,
|
||||
onBack = {
|
||||
screen.popBackStack()
|
||||
},
|
||||
statistics = {
|
||||
StatisticSummary(
|
||||
summary = statisticsViewModel.summary,
|
||||
onClass = {
|
||||
screen.navigateToCharacterSheet(name = it.label)
|
||||
},
|
||||
onDice = {
|
||||
statisticsViewModel.showDetail(dice = it)
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
HandleThrowDetailCard(
|
||||
modifier = Modifier
|
||||
.align(Alignment.BottomCenter)
|
||||
.fillMaxWidth()
|
||||
.navigationBarsPadding(),
|
||||
detail = statisticsViewModel.detail,
|
||||
onDetail = { statisticsViewModel.hideDetail() },
|
||||
)
|
||||
}
|
||||
|
||||
KeepOnScreen()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun HandleThrowDetailCard(
|
||||
modifier: Modifier = Modifier,
|
||||
detail: State<ThrowsCardUio?>,
|
||||
onDetail: () -> Unit,
|
||||
) {
|
||||
detail.value?.let {
|
||||
Dialog(
|
||||
properties = remember {
|
||||
DialogProperties(
|
||||
decorFitsSystemWindows = false,
|
||||
usePlatformDefaultWidth = false,
|
||||
)
|
||||
},
|
||||
onDismissRequest = onDetail,
|
||||
) {
|
||||
AnimatedContent(
|
||||
modifier = modifier,
|
||||
targetState = it,
|
||||
label = "ThrowCardDetailAnimation",
|
||||
transitionSpec = { fadeIn() togetherWith fadeOut() }
|
||||
) {
|
||||
ThrowsCard(
|
||||
modifier = Modifier.padding(all = 16.dp),
|
||||
throws = it,
|
||||
showDetail = remember { mutableStateOf(true) },
|
||||
onClick = onDetail,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
private fun SummaryContent(
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ data class ClassHeaderSummaryUio(
|
|||
|
||||
@Stable
|
||||
data class Dice(
|
||||
val characterName: String = "",
|
||||
val timestamp: Long = 0L,
|
||||
@DrawableRes val icon: Int = R.drawable.ic_d20_24,
|
||||
val isCriticalSuccess: Boolean = false,
|
||||
|
|
|
|||
|
|
@ -1,14 +1,52 @@
|
|||
package com.pixelized.rplexicon.ui.screens.summary.pages.statistic
|
||||
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.pixelized.rplexicon.ui.screens.summary.SummaryFactory
|
||||
import com.pixelized.rplexicon.data.repository.authentication.FirebaseRepository
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowCardFactory
|
||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||
import com.pixelized.rplexicon.ui.screens.summary.composable.ClassHeaderSummaryUio
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
|
||||
@HiltViewModel
|
||||
class StatisticViewModel @Inject constructor(
|
||||
factory: SummaryFactory,
|
||||
private val firebaseRepository: FirebaseRepository,
|
||||
private val throwCardFactory: ThrowCardFactory,
|
||||
summaryFactory: SummaryFactory,
|
||||
) : ViewModel() {
|
||||
val summary = factory.fetchSummary(viewModelScope)
|
||||
val summary = summaryFactory.fetchSummary(viewModelScope)
|
||||
|
||||
private var detailJob: Job? = null
|
||||
private val _detail = mutableStateOf<ThrowsCardUio?>(null)
|
||||
val detail: State<ThrowsCardUio?> get() = _detail
|
||||
|
||||
fun showDetail(dice: ClassHeaderSummaryUio.Dice) {
|
||||
detailJob?.cancel()
|
||||
detailJob = viewModelScope.launch(Dispatchers.IO) {
|
||||
firebaseRepository.getThrows().collect {
|
||||
val card = it.details[dice.characterName]?.let { throws ->
|
||||
throwCardFactory.convert(throws = throws)
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
_detail.value = card
|
||||
}
|
||||
}
|
||||
withContext(Dispatchers.Main) {
|
||||
_detail.value = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun hideDetail() {
|
||||
detailJob?.cancel()
|
||||
detailJob = null
|
||||
_detail.value = null
|
||||
}
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.rplexicon.ui.screens.summary
|
||||
package com.pixelized.rplexicon.ui.screens.summary.pages.statistic
|
||||
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
|
@ -22,7 +22,6 @@ 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.none
|
||||
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.mastery
|
||||
import com.pixelized.rplexicon.utilitary.extentions.local.passivesBonus
|
||||
|
|
@ -39,9 +38,6 @@ import kotlinx.coroutines.withContext
|
|||
import javax.inject.Inject
|
||||
import kotlin.math.max
|
||||
|
||||
private const val ENTER_ANIMATION_INITIAL_DELAY = 250L
|
||||
private const val ENTER_ANIMATION_DELAY = 100L
|
||||
|
||||
class SummaryFactory @Inject constructor(
|
||||
private val characterSheetRepository: CharacterSheetRepository,
|
||||
private val alterationRepository: AlterationRepository,
|
||||
|
|
@ -620,6 +616,7 @@ class SummaryFactory @Inject constructor(
|
|||
|
||||
throws.forEach { entry ->
|
||||
header.getDice(name = entry.key)?.value = ClassHeaderSummaryUio.Dice(
|
||||
characterName = entry.key,
|
||||
timestamp = entry.value.timestamp,
|
||||
result = entry.value.result,
|
||||
isCriticalSuccess = entry.value.isCriticalSuccess ?: false,
|
||||
|
|
@ -662,4 +659,9 @@ class SummaryFactory @Inject constructor(
|
|||
operator fun component1() = sheets
|
||||
operator fun component2() = fires
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ENTER_ANIMATION_INITIAL_DELAY = 250L
|
||||
private const val ENTER_ANIMATION_DELAY = 100L
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue