Add the "know what you roll" feature, allow automation after a roll.
This commit is contained in:
parent
c4df543b3d
commit
ac71765c44
14 changed files with 312 additions and 224 deletions
|
|
@ -2,6 +2,7 @@ package com.pixelized.rplexicon
|
||||||
|
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
import androidx.activity.ComponentActivity
|
import androidx.activity.ComponentActivity
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
|
|
@ -30,13 +31,12 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
|
||||||
import androidx.core.view.WindowCompat
|
import androidx.core.view.WindowCompat
|
||||||
import com.pixelized.rplexicon.ui.composable.BlurredOverlayHost
|
|
||||||
import com.pixelized.rplexicon.ui.composable.error.HandleFetchError
|
import com.pixelized.rplexicon.ui.composable.error.HandleFetchError
|
||||||
import com.pixelized.rplexicon.ui.navigation.ScreenNavHost
|
import com.pixelized.rplexicon.ui.navigation.ScreenNavHost
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.BlurredRollOverlayHostState
|
import com.pixelized.rplexicon.ui.screens.rolls.BlurredOverlayHostState
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.RollOverlay
|
import com.pixelized.rplexicon.ui.screens.rolls.BlurredRollOverlayHost
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.RollOverlayViewModel
|
import com.pixelized.rplexicon.ui.screens.rolls.RollOverlayViewModel
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.rememberBlurredRollOverlayHostState
|
import com.pixelized.rplexicon.ui.screens.rolls.rememberBlurredOverlayHostState
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.modifier.doubleBorder
|
import com.pixelized.rplexicon.utilitary.extentions.modifier.doubleBorder
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
@ -49,7 +49,7 @@ val LocalActivity = compositionLocalOf<Activity> {
|
||||||
val LocalSnack = compositionLocalOf<SnackbarHostState> {
|
val LocalSnack = compositionLocalOf<SnackbarHostState> {
|
||||||
error("SnackbarHostState not available")
|
error("SnackbarHostState not available")
|
||||||
}
|
}
|
||||||
val LocalRollOverlay = compositionLocalOf<BlurredRollOverlayHostState> {
|
val LocalRollOverlay = compositionLocalOf<BlurredOverlayHostState> {
|
||||||
error("LocalRollOverlay not yet ready")
|
error("LocalRollOverlay not yet ready")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -73,8 +73,15 @@ class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
setContent {
|
setContent {
|
||||||
val snack = remember { SnackbarHostState() }
|
val snack = remember { SnackbarHostState() }
|
||||||
val overlay = rememberBlurredRollOverlayHostState(
|
val overlay = rememberBlurredOverlayHostState(
|
||||||
viewModel = rollViewModel,
|
onPrepareRoll = { dice ->
|
||||||
|
dice?.let {
|
||||||
|
rollViewModel.prepareRoll(diceThrow = it)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onShowOverlay = { data ->
|
||||||
|
rollViewModel.setRollOverlayData(data)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
CompositionLocalProvider(
|
CompositionLocalProvider(
|
||||||
|
|
@ -94,13 +101,9 @@ class MainActivity : ComponentActivity() {
|
||||||
.padding(paddingValues = padding),
|
.padding(paddingValues = padding),
|
||||||
color = MaterialTheme.colorScheme.background
|
color = MaterialTheme.colorScheme.background
|
||||||
) {
|
) {
|
||||||
BlurredOverlayHost(
|
BlurredRollOverlayHost(
|
||||||
rollOverlayState = overlay,
|
rollViewModel = rollViewModel,
|
||||||
overlay = {
|
state = overlay,
|
||||||
RollOverlay(
|
|
||||||
viewModel = rollViewModel,
|
|
||||||
)
|
|
||||||
},
|
|
||||||
content = {
|
content = {
|
||||||
ScreenNavHost()
|
ScreenNavHost()
|
||||||
},
|
},
|
||||||
|
|
@ -150,7 +153,7 @@ class MainActivity : ComponentActivity() {
|
||||||
|
|
||||||
BackHandler(
|
BackHandler(
|
||||||
enabled = overlay.isOverlayVisible,
|
enabled = overlay.isOverlayVisible,
|
||||||
onBack = { overlay.hideOverlay() },
|
onBack = { overlay.dismiss() },
|
||||||
)
|
)
|
||||||
|
|
||||||
HandleFetchError(
|
HandleFetchError(
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ data class Item(
|
||||||
val context: String?,
|
val context: String?,
|
||||||
val isContainer: Boolean,
|
val isContainer: Boolean,
|
||||||
val effect: Throw?,
|
val effect: Throw?,
|
||||||
val usable: Boolean,
|
val consumable: Boolean,
|
||||||
val icon: Uri?,
|
val icon: Uri?,
|
||||||
) {
|
) {
|
||||||
val fullName: String = prefix?.let { "$it${name}" } ?: name
|
val fullName: String = prefix?.let { "$it${name}" } ?: name
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ class ItemLexiconParser @Inject constructor(
|
||||||
type = row.parse(column = TYPE),
|
type = row.parse(column = TYPE),
|
||||||
context = row.parse(column = CONTEXT),
|
context = row.parse(column = CONTEXT),
|
||||||
isContainer = row.parseBool(column = CONTAINER) ?: false,
|
isContainer = row.parseBool(column = CONTAINER) ?: false,
|
||||||
usable = row.parseBool(column = USABLE) ?: false,
|
consumable = row.parseBool(column = CONSUMABLE) ?: false,
|
||||||
effect = throwParser.parse(value = row.parse(column = EFFECT)),
|
effect = throwParser.parse(value = row.parse(column = EFFECT)),
|
||||||
icon = row.parseUri(column = ICON),
|
icon = row.parseUri(column = ICON),
|
||||||
)
|
)
|
||||||
|
|
@ -51,11 +51,11 @@ class ItemLexiconParser @Inject constructor(
|
||||||
private val TYPE = column("Type")
|
private val TYPE = column("Type")
|
||||||
private val CONTEXT = column("Contexte")
|
private val CONTEXT = column("Contexte")
|
||||||
private val CONTAINER = column("Contenant")
|
private val CONTAINER = column("Contenant")
|
||||||
private val USABLE = column("Utilisable")
|
private val CONSUMABLE = column("Consommable")
|
||||||
private val EFFECT = column("Effet")
|
private val EFFECT = column("Effet")
|
||||||
private val ICON = column("Icone")
|
private val ICON = column("Icone")
|
||||||
|
|
||||||
private val COLUMNS =
|
private val COLUMNS =
|
||||||
listOf(ID, PREFIX, NAME, TYPE, CONTEXT, CONTAINER, USABLE, EFFECT, ICON)
|
listOf(ID, PREFIX, NAME, TYPE, CONTEXT, CONTAINER, CONSUMABLE, EFFECT, ICON)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
package com.pixelized.rplexicon.ui.composable
|
|
||||||
|
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
|
||||||
import androidx.compose.animation.core.animateDpAsState
|
|
||||||
import androidx.compose.animation.fadeIn
|
|
||||||
import androidx.compose.animation.fadeOut
|
|
||||||
import androidx.compose.animation.slideInVertically
|
|
||||||
import androidx.compose.animation.slideOutVertically
|
|
||||||
import androidx.compose.foundation.background
|
|
||||||
import androidx.compose.foundation.layout.Box
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
|
||||||
import androidx.compose.foundation.layout.systemBarsPadding
|
|
||||||
import androidx.compose.material3.MaterialTheme
|
|
||||||
import androidx.compose.material3.Surface
|
|
||||||
import androidx.compose.runtime.Composable
|
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.Stable
|
|
||||||
import androidx.compose.runtime.getValue
|
|
||||||
import androidx.compose.runtime.mutableStateOf
|
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Modifier
|
|
||||||
import androidx.compose.ui.draw.BlurredEdgeTreatment
|
|
||||||
import androidx.compose.ui.draw.blur
|
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
|
||||||
import com.pixelized.rplexicon.utilitary.extentions.modifier.clickableInterceptor
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
interface BlurredOverlayHostState {
|
|
||||||
val isOverlayVisible: Boolean
|
|
||||||
fun showOverlay()
|
|
||||||
fun hideOverlay()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
private class BlurredOverlayHostStateImpl(
|
|
||||||
rollOverlayVisibilityState: MutableState<Boolean>,
|
|
||||||
) : BlurredOverlayHostState {
|
|
||||||
override var isOverlayVisible by rollOverlayVisibilityState
|
|
||||||
|
|
||||||
override fun showOverlay() {
|
|
||||||
isOverlayVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideOverlay() {
|
|
||||||
isOverlayVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@Stable
|
|
||||||
fun rememberBlurredOverlayHostState(): BlurredOverlayHostState {
|
|
||||||
val rollOverlayVisibilityState = rememberSaveable { mutableStateOf(false) }
|
|
||||||
return remember {
|
|
||||||
BlurredOverlayHostStateImpl(
|
|
||||||
rollOverlayVisibilityState = rollOverlayVisibilityState
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
fun BlurredOverlayHost(
|
|
||||||
rollOverlayState: BlurredOverlayHostState = rememberBlurredOverlayHostState(),
|
|
||||||
overlay: @Composable () -> Unit,
|
|
||||||
content: @Composable () -> Unit,
|
|
||||||
) {
|
|
||||||
val density = LocalDensity.current
|
|
||||||
|
|
||||||
Surface {
|
|
||||||
val blurs = animateDpAsState(
|
|
||||||
targetValue = if (rollOverlayState.isOverlayVisible) 4.dp else 0.dp,
|
|
||||||
label = "RollOverlayHostBlurAnimation",
|
|
||||||
)
|
|
||||||
Box(
|
|
||||||
modifier = Modifier.blur(
|
|
||||||
radius = blurs.value,
|
|
||||||
edgeTreatment = BlurredEdgeTreatment.Unbounded,
|
|
||||||
),
|
|
||||||
content = { content() },
|
|
||||||
)
|
|
||||||
AnimatedVisibility(
|
|
||||||
visible = rollOverlayState.isOverlayVisible,
|
|
||||||
enter = fadeIn() + slideInVertically { with(density) { 64.dp.roundToPx() } },
|
|
||||||
exit = fadeOut() + slideOutVertically { with(density) { 64.dp.roundToPx() } },
|
|
||||||
content = {
|
|
||||||
Box(
|
|
||||||
modifier = Modifier
|
|
||||||
.clickableInterceptor()
|
|
||||||
.background(color = MaterialTheme.lexicon.colorScheme.rollOverlayBrush)
|
|
||||||
.fillMaxSize()
|
|
||||||
.systemBarsPadding(),
|
|
||||||
) {
|
|
||||||
overlay()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -59,6 +59,7 @@ import com.pixelized.rplexicon.NO_WINDOW_INSETS
|
||||||
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.composable.Loader
|
import com.pixelized.rplexicon.ui.composable.Loader
|
||||||
|
import com.pixelized.rplexicon.ui.screens.rolls.RollResult
|
||||||
import com.pixelized.rplexicon.ui.composable.Toolbar
|
import com.pixelized.rplexicon.ui.composable.Toolbar
|
||||||
import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog
|
import com.pixelized.rplexicon.ui.composable.edit.HandleHitPointEditDialog
|
||||||
import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog
|
import com.pixelized.rplexicon.ui.composable.edit.HandleSkillEditDialog
|
||||||
|
|
@ -83,9 +84,9 @@ import com.pixelized.rplexicon.ui.screens.character.pages.actions.SpellsViewMode
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPage
|
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPage
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPagePreview
|
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationPagePreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationViewModel
|
import com.pixelized.rplexicon.ui.screens.character.pages.alteration.AlterationViewModel
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD.InventoryViewModelOLD
|
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage2
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPage2
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPreview
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.InventoryPreview
|
||||||
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory_OLD.InventoryViewModelOLD
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPage
|
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPage
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPreview
|
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyPreview
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyViewModel
|
import com.pixelized.rplexicon.ui.screens.character.pages.proficiency.ProficiencyViewModel
|
||||||
|
|
@ -149,8 +150,7 @@ fun CharacterSheetScreen(
|
||||||
},
|
},
|
||||||
onInitiative = {
|
onInitiative = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = headerViewModel.initiativeRoll())
|
overlay.showOverlay(diceThrow = headerViewModel.initiativeRoll())
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onHitPoint = headerViewModel::toggleHitPointDialog,
|
onHitPoint = headerViewModel::toggleHitPointDialog,
|
||||||
|
|
@ -159,8 +159,16 @@ fun CharacterSheetScreen(
|
||||||
},
|
},
|
||||||
onDeathRoll = {
|
onDeathRoll = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = headerViewModel.onDeathThrow())
|
val dices = headerViewModel.onDeathThrow()
|
||||||
overlay.showOverlay()
|
val result = overlay.showOverlay(diceThrow = dices)
|
||||||
|
if (result is RollResult.Roll) {
|
||||||
|
when {
|
||||||
|
result.isCriticalSuccess -> headerViewModel.onDeathSuccess(critical = true)
|
||||||
|
result.isCriticalFailure -> headerViewModel.onDeathFailure(critical = true)
|
||||||
|
result.value < 10 -> headerViewModel.onDeathFailure()
|
||||||
|
else -> headerViewModel.onDeathSuccess()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDeathSuccess = headerViewModel::onDeathSuccess,
|
onDeathSuccess = headerViewModel::onDeathSuccess,
|
||||||
|
|
@ -203,13 +211,12 @@ fun CharacterSheetScreen(
|
||||||
onLevel = { spell, level ->
|
onLevel = { spell, level ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
sheetState.hide()
|
sheetState.hide()
|
||||||
overlay.prepareRoll(
|
overlay.showOverlay(
|
||||||
diceThrow = spellsViewModel.onCastSpell(
|
diceThrow = spellsViewModel.onCastSpell(
|
||||||
spell,
|
spell,
|
||||||
level
|
level
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
@ -237,7 +244,7 @@ fun CharacterSheetScreen(
|
||||||
}
|
}
|
||||||
|
|
||||||
BackHandler(enabled = overlay.isOverlayVisible) {
|
BackHandler(enabled = overlay.isOverlayVisible) {
|
||||||
overlay.hideOverlay()
|
overlay.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
KeepOnScreen()
|
KeepOnScreen()
|
||||||
|
|
|
||||||
|
|
@ -63,16 +63,14 @@ fun ActionPage(
|
||||||
onAttackHit = { id ->
|
onAttackHit = { id ->
|
||||||
attacksViewModel.onHitRoll(id)?.let {
|
attacksViewModel.onHitRoll(id)?.let {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = it)
|
overlay.showOverlay(diceThrow = it)
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onAttackDamage = { id ->
|
onAttackDamage = { id ->
|
||||||
attacksViewModel.onDamageRoll(id)?.let {
|
attacksViewModel.onDamageRoll(id)?.let {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = it)
|
overlay.showOverlay(diceThrow = it)
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -81,8 +79,7 @@ fun ActionPage(
|
||||||
},
|
},
|
||||||
onSkillThrow = {
|
onSkillThrow = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = skillViewModel.onSkillRoll(it.label))
|
overlay.showOverlay(diceThrow = skillViewModel.onSkillRoll(it.label))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSkillInfo = {
|
onSkillInfo = {
|
||||||
|
|
@ -100,14 +97,12 @@ fun ActionPage(
|
||||||
},
|
},
|
||||||
onSpellHit = { id ->
|
onSpellHit = { id ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = spellsViewModel.onSpellHitRoll(id))
|
overlay.showOverlay(diceThrow = spellsViewModel.onSpellHitRoll(id))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSpellDamage = { id ->
|
onSpellDamage = { id ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = spellsViewModel.onSpellDamageRoll(id))
|
overlay.showOverlay(diceThrow = spellsViewModel.onSpellDamageRoll(id))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onCast = {
|
onCast = {
|
||||||
|
|
@ -116,8 +111,7 @@ fun ActionPage(
|
||||||
scope.launch { sheetState.show() }
|
scope.launch { sheetState.show() }
|
||||||
} else {
|
} else {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = spellsViewModel.onCastSpell(it))
|
overlay.showOverlay(diceThrow = spellsViewModel.onCastSpell(it))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -113,19 +113,25 @@ class HeaderViewModel @Inject constructor(
|
||||||
return DiceThrow.DeathSavingThrow(character = character)
|
return DiceThrow.DeathSavingThrow(character = character)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDeathSuccess() {
|
fun onDeathSuccess(
|
||||||
|
critical: Boolean = false,
|
||||||
|
) {
|
||||||
|
val token = if (critical) 2 else 1
|
||||||
firebaseRepository.setCharacterDeathCounter(
|
firebaseRepository.setCharacterDeathCounter(
|
||||||
character = character,
|
character = character,
|
||||||
success = ((fireData.value?.deathSuccess ?: 0) + 1) % 4,
|
success = ((fireData.value?.deathSuccess ?: 0) + token) % 4,
|
||||||
failure = fireData.value?.deathFailure ?: 0,
|
failure = fireData.value?.deathFailure ?: 0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onDeathFailure() {
|
fun onDeathFailure(
|
||||||
|
critical: Boolean = false,
|
||||||
|
) {
|
||||||
|
val token = if (critical) 2 else 1
|
||||||
firebaseRepository.setCharacterDeathCounter(
|
firebaseRepository.setCharacterDeathCounter(
|
||||||
character = character,
|
character = character,
|
||||||
success = fireData.value?.deathSuccess ?: 0,
|
success = fireData.value?.deathSuccess ?: 0,
|
||||||
failure = ((fireData.value?.deathFailure ?: 0) + 1) % 4,
|
failure = ((fireData.value?.deathFailure ?: 0) + token) % 4,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,7 @@ import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.ItemDetailViewModel
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_detail.ItemDetailViewModel
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListDialog
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListDialog
|
||||||
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListViewModel
|
import com.pixelized.rplexicon.ui.screens.character.pages.inventory.item_list.ItemListViewModel
|
||||||
|
import com.pixelized.rplexicon.ui.screens.rolls.RollResult
|
||||||
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
import com.pixelized.rplexicon.ui.theme.LexiconTheme
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
|
@ -107,11 +108,14 @@ fun InventoryPage2(
|
||||||
},
|
},
|
||||||
onItemUse = { id, quantity ->
|
onItemUse = { id, quantity ->
|
||||||
// try to roll the dices.
|
// try to roll the dices.
|
||||||
val diceThrow = inventoryViewModel.useItem(itemId = id)
|
scope.launch {
|
||||||
if (diceThrow != null) {
|
val (item, dices) = inventoryViewModel.useItem(itemId = id)
|
||||||
scope.launch {
|
val result = overlay.showOverlay(diceThrow = dices)
|
||||||
overlay.prepareRoll(diceThrow = diceThrow)
|
if (result is RollResult.Roll && item?.consumable == true) {
|
||||||
overlay.showOverlay()
|
inventoryViewModel.setItemQuantity(
|
||||||
|
itemId = id,
|
||||||
|
quantity = quantity - 1
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -141,10 +145,14 @@ fun InventoryPage2(
|
||||||
// hide the detail dialog
|
// hide the detail dialog
|
||||||
itemDetailViewModel.hide()
|
itemDetailViewModel.hide()
|
||||||
// try to roll the dices.
|
// try to roll the dices.
|
||||||
inventoryViewModel.useItem(itemId = detail.id)?.let { diceThrow ->
|
scope.launch {
|
||||||
scope.launch {
|
val (item, dices) = inventoryViewModel.useItem(itemId = detail.id)
|
||||||
overlay.prepareRoll(diceThrow = diceThrow)
|
val result = overlay.showOverlay(diceThrow = dices)
|
||||||
overlay.showOverlay()
|
if (result is RollResult.Roll && item?.consumable == true) {
|
||||||
|
inventoryViewModel.setItemQuantity(
|
||||||
|
itemId = detail.id,
|
||||||
|
quantity = detail.quantity?.minus(1) ?: 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ import androidx.lifecycle.SavedStateHandle
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.pixelized.rplexicon.data.model.DiceThrow
|
import com.pixelized.rplexicon.data.model.DiceThrow
|
||||||
|
import com.pixelized.rplexicon.data.model.item.Item
|
||||||
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
import com.pixelized.rplexicon.data.repository.character.CharacterSheetRepository
|
||||||
import com.pixelized.rplexicon.data.repository.character.ItemsRepository
|
import com.pixelized.rplexicon.data.repository.character.ItemsRepository
|
||||||
import com.pixelized.rplexicon.data.repository.firebase.inventory.InventoryFireRepository
|
import com.pixelized.rplexicon.data.repository.firebase.inventory.InventoryFireRepository
|
||||||
|
|
@ -329,16 +330,18 @@ class InventoryViewModel @Inject constructor(
|
||||||
|
|
||||||
fun useItem(
|
fun useItem(
|
||||||
itemId: String,
|
itemId: String,
|
||||||
): DiceThrow? {
|
): Pair<Item?, DiceThrow?> {
|
||||||
val item = itemRepository.find(id = itemId)
|
val item = itemRepository.find(id = itemId)
|
||||||
return if (item?.effect != null) {
|
return if (item == null) {
|
||||||
DiceThrow.Object(
|
null to null
|
||||||
character = character,
|
|
||||||
itemId = item.id,
|
|
||||||
itemName = item.name,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
null
|
item to item.effect?.let {
|
||||||
|
DiceThrow.Object(
|
||||||
|
character = character,
|
||||||
|
itemId = item.id,
|
||||||
|
itemName = item.name,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -112,8 +112,7 @@ fun InventoryPageOLD(
|
||||||
// detailViewModel.hide(detail)
|
// detailViewModel.hide(detail)
|
||||||
viewModel.onUse(itemId = detail.id)?.let { diceThrow ->
|
viewModel.onUse(itemId = detail.id)?.let { diceThrow ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = diceThrow)
|
overlay.showOverlay(diceThrow = diceThrow)
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,14 +83,12 @@ fun ProficiencyPage(
|
||||||
passives = viewModel.skills,
|
passives = viewModel.skills,
|
||||||
onStats = { stat ->
|
onStats = { stat ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = viewModel.statRoll(stat.id))
|
overlay.showOverlay(diceThrow = viewModel.statRoll(stat.id))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onProficiencies = { proficiency ->
|
onProficiencies = { proficiency ->
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = viewModel.proficiencyRoll(proficiency.id))
|
overlay.showOverlay(diceThrow = viewModel.proficiencyRoll(proficiency.id))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSkillCount = {
|
onSkillCount = {
|
||||||
|
|
@ -98,8 +96,7 @@ fun ProficiencyPage(
|
||||||
},
|
},
|
||||||
onSkillThrow = {
|
onSkillThrow = {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
overlay.prepareRoll(diceThrow = viewModel.onSkillRoll(it.label))
|
overlay.showOverlay(diceThrow = viewModel.onSkillRoll(it.label))
|
||||||
overlay.showOverlay()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onSkillInfo = {
|
onSkillInfo = {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,216 @@
|
||||||
|
package com.pixelized.rplexicon.ui.screens.rolls
|
||||||
|
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
|
import androidx.compose.animation.fadeIn
|
||||||
|
import androidx.compose.animation.fadeOut
|
||||||
|
import androidx.compose.animation.slideInVertically
|
||||||
|
import androidx.compose.animation.slideOutVertically
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.systemBarsPadding
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
|
import androidx.compose.runtime.State
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberUpdatedState
|
||||||
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.BlurredEdgeTreatment
|
||||||
|
import androidx.compose.ui.draw.blur
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.pixelized.rplexicon.data.model.DiceThrow
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.lexicon
|
||||||
|
import com.pixelized.rplexicon.utilitary.extentions.modifier.clickableInterceptor
|
||||||
|
import kotlinx.coroutines.CancellableContinuation
|
||||||
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
|
import kotlin.coroutines.resume
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
interface BlurredOverlayHostState {
|
||||||
|
val isOverlayVisible: Boolean
|
||||||
|
val overlayData: BlurredOverlayData?
|
||||||
|
|
||||||
|
suspend fun showOverlay(diceThrow: DiceThrow?): RollResult
|
||||||
|
fun dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
interface BlurredOverlayData {
|
||||||
|
val diceThrow: DiceThrow
|
||||||
|
|
||||||
|
fun setRollValue(
|
||||||
|
value: Int,
|
||||||
|
isCriticalSuccess: Boolean,
|
||||||
|
isCriticalFailure: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
|
fun dismiss()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
sealed class RollResult {
|
||||||
|
data class Roll(
|
||||||
|
val value: Int,
|
||||||
|
val isCriticalSuccess: Boolean,
|
||||||
|
val isCriticalFailure: Boolean,
|
||||||
|
) : RollResult()
|
||||||
|
|
||||||
|
data object Dismissed : RollResult()
|
||||||
|
|
||||||
|
data object Void : RollResult()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
private class BlurredOverlayHostStateImpl(
|
||||||
|
rollOverlayVisibilityState: MutableState<Boolean>,
|
||||||
|
private val onPrepareRoll: State<suspend (DiceThrow?) -> Unit>,
|
||||||
|
private val onShowOverlay: State<(BlurredOverlayData) -> Unit>,
|
||||||
|
) : BlurredOverlayHostState {
|
||||||
|
private val mutex = Mutex()
|
||||||
|
|
||||||
|
private var _currentBlurredOverlayData: BlurredOverlayDataImpl? by mutableStateOf(null)
|
||||||
|
override val overlayData: BlurredOverlayData? get() = _currentBlurredOverlayData
|
||||||
|
|
||||||
|
override var isOverlayVisible by rollOverlayVisibilityState
|
||||||
|
|
||||||
|
override suspend fun showOverlay(
|
||||||
|
diceThrow: DiceThrow?,
|
||||||
|
): RollResult {
|
||||||
|
return if (diceThrow == null) {
|
||||||
|
RollResult.Void
|
||||||
|
} else {
|
||||||
|
mutex.withLock {
|
||||||
|
try {
|
||||||
|
onPrepareRoll.value.invoke(diceThrow)
|
||||||
|
isOverlayVisible = true
|
||||||
|
return suspendCancellableCoroutine { continuation ->
|
||||||
|
val data = BlurredOverlayDataImpl(
|
||||||
|
continuation = continuation,
|
||||||
|
diceThrow = diceThrow
|
||||||
|
)
|
||||||
|
_currentBlurredOverlayData = data
|
||||||
|
onShowOverlay.value.invoke(data)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
_currentBlurredOverlayData = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dismiss() {
|
||||||
|
isOverlayVisible = false
|
||||||
|
_currentBlurredOverlayData?.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BlurredOverlayDataImpl(
|
||||||
|
private val continuation: CancellableContinuation<RollResult>,
|
||||||
|
override val diceThrow: DiceThrow,
|
||||||
|
) : BlurredOverlayData {
|
||||||
|
|
||||||
|
private var result: RollResult = RollResult.Dismissed
|
||||||
|
|
||||||
|
override fun setRollValue(
|
||||||
|
value: Int,
|
||||||
|
isCriticalSuccess: Boolean,
|
||||||
|
isCriticalFailure: Boolean,
|
||||||
|
) {
|
||||||
|
if (continuation.isActive) {
|
||||||
|
result = RollResult.Roll(
|
||||||
|
value = value,
|
||||||
|
isCriticalSuccess = isCriticalSuccess,
|
||||||
|
isCriticalFailure = isCriticalFailure,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dismiss() {
|
||||||
|
if (continuation.isActive) {
|
||||||
|
continuation.resume(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other == null || this::class != other::class) return false
|
||||||
|
other as BlurredOverlayDataImpl
|
||||||
|
return continuation == other.continuation
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return continuation.hashCode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Stable
|
||||||
|
fun rememberBlurredOverlayHostState(
|
||||||
|
onPrepareRoll: suspend (DiceThrow?) -> Unit,
|
||||||
|
onShowOverlay: (BlurredOverlayData) -> Unit,
|
||||||
|
): BlurredOverlayHostState {
|
||||||
|
val rollOverlayVisibilityState = rememberSaveable { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val currentOnPrepareRoll = rememberUpdatedState(newValue = onPrepareRoll)
|
||||||
|
val currentOnShowOverlay = rememberUpdatedState(newValue = onShowOverlay)
|
||||||
|
|
||||||
|
return remember(currentOnShowOverlay, rollOverlayVisibilityState) {
|
||||||
|
BlurredOverlayHostStateImpl(
|
||||||
|
rollOverlayVisibilityState = rollOverlayVisibilityState,
|
||||||
|
onPrepareRoll = currentOnPrepareRoll,
|
||||||
|
onShowOverlay = currentOnShowOverlay,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun BlurredRollOverlayHost(
|
||||||
|
rollViewModel: RollOverlayViewModel,
|
||||||
|
state: BlurredOverlayHostState,
|
||||||
|
content: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
val density = LocalDensity.current
|
||||||
|
|
||||||
|
Surface {
|
||||||
|
val blurs = animateDpAsState(
|
||||||
|
targetValue = if (state.isOverlayVisible) 4.dp else 0.dp,
|
||||||
|
label = "RollOverlayHostBlurAnimation",
|
||||||
|
)
|
||||||
|
Box(
|
||||||
|
modifier = Modifier.blur(
|
||||||
|
radius = blurs.value,
|
||||||
|
edgeTreatment = BlurredEdgeTreatment.Unbounded,
|
||||||
|
),
|
||||||
|
content = { content() },
|
||||||
|
)
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = state.isOverlayVisible,
|
||||||
|
enter = fadeIn() + slideInVertically { with(density) { 64.dp.roundToPx() } },
|
||||||
|
exit = fadeOut() + slideOutVertically { with(density) { 64.dp.roundToPx() } },
|
||||||
|
content = {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.clickableInterceptor()
|
||||||
|
.background(color = MaterialTheme.lexicon.colorScheme.rollOverlayBrush)
|
||||||
|
.fillMaxSize()
|
||||||
|
.systemBarsPadding(),
|
||||||
|
) {
|
||||||
|
RollOverlay(
|
||||||
|
viewModel = rollViewModel,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,16 +5,9 @@ import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ContentTransform
|
|
||||||
import androidx.compose.animation.SizeTransform
|
|
||||||
import androidx.compose.animation.core.Animatable
|
import androidx.compose.animation.core.Animatable
|
||||||
import androidx.compose.animation.core.AnimationVector1D
|
import androidx.compose.animation.core.AnimationVector1D
|
||||||
import androidx.compose.animation.core.animateDpAsState
|
import androidx.compose.animation.core.animateDpAsState
|
||||||
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.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||||
import androidx.compose.foundation.isSystemInDarkTheme
|
import androidx.compose.foundation.isSystemInDarkTheme
|
||||||
|
|
@ -42,7 +35,6 @@ import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TextButton
|
import androidx.compose.material3.TextButton
|
||||||
import androidx.compose.material3.rememberDrawerState
|
import androidx.compose.material3.rememberDrawerState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.MutableState
|
|
||||||
import androidx.compose.runtime.Stable
|
import androidx.compose.runtime.Stable
|
||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.derivedStateOf
|
import androidx.compose.runtime.derivedStateOf
|
||||||
|
|
@ -50,13 +42,10 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
|
||||||
import androidx.compose.runtime.setValue
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.composed
|
import androidx.compose.ui.composed
|
||||||
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.text.AnnotatedString
|
import androidx.compose.ui.text.AnnotatedString
|
||||||
|
|
@ -65,7 +54,6 @@ import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameter
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import androidx.compose.ui.unit.Density
|
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
import androidx.compose.ui.unit.LayoutDirection
|
import androidx.compose.ui.unit.LayoutDirection
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
|
@ -73,9 +61,7 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
||||||
import com.pixelized.rplexicon.LocalRollOverlay
|
import com.pixelized.rplexicon.LocalRollOverlay
|
||||||
import com.pixelized.rplexicon.NO_WINDOW_INSETS
|
import com.pixelized.rplexicon.NO_WINDOW_INSETS
|
||||||
import com.pixelized.rplexicon.R
|
import com.pixelized.rplexicon.R
|
||||||
import com.pixelized.rplexicon.data.model.DiceThrow
|
|
||||||
import com.pixelized.rplexicon.isInDarkTheme
|
import com.pixelized.rplexicon.isInDarkTheme
|
||||||
import com.pixelized.rplexicon.ui.composable.BlurredOverlayHostState
|
|
||||||
import com.pixelized.rplexicon.ui.composable.CategoryHeader
|
import com.pixelized.rplexicon.ui.composable.CategoryHeader
|
||||||
import com.pixelized.rplexicon.ui.composable.ModalNavigationDrawer
|
import com.pixelized.rplexicon.ui.composable.ModalNavigationDrawer
|
||||||
import com.pixelized.rplexicon.ui.composable.Toolbar
|
import com.pixelized.rplexicon.ui.composable.Toolbar
|
||||||
|
|
@ -87,7 +73,6 @@ import com.pixelized.rplexicon.ui.screens.rolls.composable.RollDiceUio
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
|
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCard
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
import com.pixelized.rplexicon.ui.screens.rolls.composable.ThrowsCardUio
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.rememberSlideInOutAnimation
|
import com.pixelized.rplexicon.ui.screens.rolls.composable.rememberSlideInOutAnimation
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.composable.slideInOutAnimation
|
|
||||||
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
|
import com.pixelized.rplexicon.ui.screens.rolls.preview.rememberRollAlterations
|
||||||
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
|
||||||
|
|
@ -118,7 +103,7 @@ fun RollOverlay(
|
||||||
scope.launch { drawer.close() }
|
scope.launch { drawer.close() }
|
||||||
},
|
},
|
||||||
onClose = {
|
onClose = {
|
||||||
overlay.hideOverlay()
|
overlay.dismiss()
|
||||||
},
|
},
|
||||||
onDice = {
|
onDice = {
|
||||||
viewModel.roll(uiScope = scope)
|
viewModel.roll(uiScope = scope)
|
||||||
|
|
@ -466,43 +451,4 @@ private class RollOverlayPreviewProvider : PreviewParameterProvider<RollOverlayP
|
||||||
card = mutableStateOf(null),
|
card = mutableStateOf(null),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
interface BlurredRollOverlayHostState : BlurredOverlayHostState {
|
|
||||||
suspend fun prepareRoll(diceThrow: DiceThrow)
|
|
||||||
}
|
|
||||||
|
|
||||||
@Stable
|
|
||||||
private class BlurredRollOverlayHostStateImpl(
|
|
||||||
private val viewModel: RollOverlayViewModel,
|
|
||||||
rollOverlayVisibilityState: MutableState<Boolean>,
|
|
||||||
) : BlurredRollOverlayHostState {
|
|
||||||
override var isOverlayVisible by rollOverlayVisibilityState
|
|
||||||
|
|
||||||
override suspend fun prepareRoll(diceThrow: DiceThrow) {
|
|
||||||
viewModel.prepareRoll(diceThrow)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun showOverlay() {
|
|
||||||
isOverlayVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun hideOverlay() {
|
|
||||||
isOverlayVisible = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
@Stable
|
|
||||||
fun rememberBlurredRollOverlayHostState(
|
|
||||||
viewModel: RollOverlayViewModel,
|
|
||||||
): BlurredRollOverlayHostState {
|
|
||||||
val rollOverlayVisibilityState = rememberSaveable { mutableStateOf(false) }
|
|
||||||
return remember {
|
|
||||||
BlurredRollOverlayHostStateImpl(
|
|
||||||
viewModel = viewModel,
|
|
||||||
rollOverlayVisibilityState = rollOverlayVisibilityState
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -62,6 +62,7 @@ class RollOverlayViewModel @Inject constructor(
|
||||||
activeAlterationRepository: ActiveAlterationRepository,
|
activeAlterationRepository: ActiveAlterationRepository,
|
||||||
application: Application,
|
application: Application,
|
||||||
) : AndroidViewModel(application) {
|
) : AndroidViewModel(application) {
|
||||||
|
private var _overlay: BlurredOverlayData? = null
|
||||||
private val _diceThrow = MutableStateFlow<DiceThrow?>(null)
|
private val _diceThrow = MutableStateFlow<DiceThrow?>(null)
|
||||||
|
|
||||||
private val _alterationsOverride = MutableStateFlow<Map<String, Boolean>>(emptyMap())
|
private val _alterationsOverride = MutableStateFlow<Map<String, Boolean>>(emptyMap())
|
||||||
|
|
@ -126,6 +127,10 @@ class RollOverlayViewModel @Inject constructor(
|
||||||
private val _alterationDetailDialog = mutableStateOf<AlterationDialogDetailUio?>(null)
|
private val _alterationDetailDialog = mutableStateOf<AlterationDialogDetailUio?>(null)
|
||||||
val alterationDetailDialog: State<AlterationDialogDetailUio?> get() = _alterationDetailDialog
|
val alterationDetailDialog: State<AlterationDialogDetailUio?> get() = _alterationDetailDialog
|
||||||
|
|
||||||
|
fun setRollOverlayData(data: BlurredOverlayData) {
|
||||||
|
_overlay = data
|
||||||
|
}
|
||||||
|
|
||||||
suspend fun prepareRoll(diceThrow: DiceThrow) {
|
suspend fun prepareRoll(diceThrow: DiceThrow) {
|
||||||
// save the dice throw.
|
// save the dice throw.
|
||||||
_diceThrow.value = diceThrow
|
_diceThrow.value = diceThrow
|
||||||
|
|
@ -184,6 +189,11 @@ class RollOverlayViewModel @Inject constructor(
|
||||||
delay(RollDiceUio.ROLL_DURATION.toLong())
|
delay(RollDiceUio.ROLL_DURATION.toLong())
|
||||||
// display the roll result & share with other player
|
// display the roll result & share with other player
|
||||||
if (isActive) {
|
if (isActive) {
|
||||||
|
_overlay?.setRollValue(
|
||||||
|
value = result.throws.result.toIntOrNull() ?: 0,
|
||||||
|
isCriticalSuccess = result.throws.isCriticalSuccess ?: false,
|
||||||
|
isCriticalFailure = result.throws.isCriticalFailure ?: false,
|
||||||
|
)
|
||||||
_dice.value = result.dice
|
_dice.value = result.dice
|
||||||
// share the result
|
// share the result
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue