From 5ac0c2dcf6fa35b9f7da037db611e544733699be Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Tue, 12 Nov 2024 16:57:54 +0100 Subject: [PATCH] Change the blur mechanism --- .../lwa/composable/blur/BlurContent.kt | 74 ++++++++++++ .../composable/decoratedBox/DecoratedBox.kt | 2 +- .../detail/CharacterSheetPage.kt | 114 +++++++++++------- .../detail/CharacterSheetViewModel.kt | 19 ++- .../CharacterSheetDeleteConfirmationDialog.kt | 13 +- .../detail/dialog/CharacterSheetStatDialog.kt | 16 +-- .../desktop/lwa/theme/LwaColorPalette.kt | 7 ++ 7 files changed, 172 insertions(+), 73 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/blur/BlurContent.kt create mode 100644 composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/theme/LwaColorPalette.kt diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/blur/BlurContent.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/blur/BlurContent.kt new file mode 100644 index 0000000..c743d14 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/blur/BlurContent.kt @@ -0,0 +1,74 @@ +package com.pixelized.desktop.lwa.composable.blur + +import androidx.compose.animation.animateColor +import androidx.compose.animation.core.animateDp +import androidx.compose.animation.core.updateTransition +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.State +import androidx.compose.runtime.mutableStateOf +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.BlurredEdgeTreatment +import androidx.compose.ui.draw.blur +import androidx.compose.ui.draw.drawWithContent +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.theme.LwaColorPalette + +@Stable +class BlurContentController( + blurred: Boolean = false, + val blurredRadius: Dp = 8.dp, + val scrimColor: Color = LwaColorPalette.DefaultScrimColor, +) { + private val _blurred = mutableStateOf(blurred) + val isBlurred: State get() = _blurred + + fun show() { + _blurred.value = true + } + + fun hide() { + _blurred.value = false + } +} + +@Composable +fun BlurContent( + modifier: Modifier = Modifier, + controller: BlurContentController, + content: @Composable BoxScope.() -> Unit, +) { + val transition = updateTransition( + targetState = controller.isBlurred.value, + ) + val animatedBlur = transition.animateDp { + when (it) { + true -> controller.blurredRadius + else -> 0.dp + } + } + val animatedBackground = transition.animateColor { + when (it) { + true -> controller.scrimColor + else -> controller.scrimColor.copy(alpha = 0f) + } + } + Box( + modifier = modifier + ) { + Box( + modifier = Modifier + .matchParentSize() + .blur(radius = animatedBlur.value, edgeTreatment = BlurredEdgeTreatment.Unbounded) + .drawWithContent { + drawContent() + drawRect(color = animatedBackground.value) + }, + content = content, + ) + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/decoratedBox/DecoratedBox.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/decoratedBox/DecoratedBox.kt index 57b7713..69f18e7 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/decoratedBox/DecoratedBox.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/composable/decoratedBox/DecoratedBox.kt @@ -18,7 +18,7 @@ import org.jetbrains.compose.ui.tooling.preview.Preview @Composable fun DecoratedBox( modifier: Modifier = Modifier, - border: Color = Color(0xFFDFDFDF), + border: Color = Color(0xFF909090), content: @Composable BoxScope.() -> Unit, ) { Box( diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt index 6421e67..bf151ab 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetPage.kt @@ -1,8 +1,15 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail +import androidx.compose.animation.AnimatedContent +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.ScrollState import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row @@ -30,6 +37,7 @@ import androidx.compose.material.icons.filled.Delete import androidx.compose.material.icons.filled.Edit import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -40,9 +48,9 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.createSavedStateHandle import androidx.lifecycle.viewmodel.compose.viewModel import com.pixelized.desktop.lwa.LocalWindowController +import com.pixelized.desktop.lwa.composable.blur.BlurContent +import com.pixelized.desktop.lwa.composable.blur.BlurContentController import com.pixelized.desktop.lwa.composable.decoratedBox.DecoratedBox -import com.pixelized.desktop.lwa.composable.overlay.BlurOverlay -import com.pixelized.desktop.lwa.composable.overlay.BlurOverlayViewModel import com.pixelized.desktop.lwa.navigation.LocalScreenController import com.pixelized.desktop.lwa.navigation.destination.navigateToCharacterSheetEdit import com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog.CharacterSheetDeleteConfirmationDialog @@ -97,24 +105,18 @@ fun CharacterSheetPage( viewModel: CharacterSheetViewModel = viewModel { CharacterSheetViewModel(savedStateHandle = createSavedStateHandle()) }, - overlayViewModel: BlurOverlayViewModel = viewModel { BlurOverlayViewModel() }, rollViewModel: RollViewModel = viewModel { RollViewModel() }, ) { val window = LocalWindowController.current val screen = LocalScreenController.current val scope = rememberCoroutineScope() + val blurController = remember { BlurContentController() } Surface( modifier = Modifier.fillMaxSize(), ) { - BlurOverlay( - viewModel = overlayViewModel, - overlay = { - RollPage( - viewModel = rollViewModel, - onDismissRequest = overlayViewModel::hide, - ) - }, + BlurContent( + controller = blurController, content = { viewModel.sheet.value?.let { sheet -> CharacterSheetPageContent( @@ -127,61 +129,91 @@ fun CharacterSheetPage( ) }, onDelete = { + blurController.show() viewModel.showConfirmCharacterDeletionDialog() }, onCharacteristic = { characteristic -> + blurController.show() rollViewModel.prepareRoll( sheet = sheet, characteristic = characteristic ) - overlayViewModel.show() + viewModel.showRollOverlay() }, onSubCharacteristic = { + blurController.show() viewModel.showSubCharacteristicDialog(id = it.id) }, onSkill = { node -> + blurController.show() rollViewModel.prepareRoll(sheet = sheet, node = node) - overlayViewModel.show() + viewModel.showRollOverlay() }, onUseSkill = viewModel::onUseSkill, onRoll = { roll -> + blurController.show() rollViewModel.prepareRoll(sheet = sheet, roll = roll) - overlayViewModel.show() + viewModel.showRollOverlay() }, ) } }, ) - } - CharacterSheetDeleteConfirmationDialog( - dialog = viewModel.displayDeleteConfirmationDialog, - onConfirm = { - scope.launch { - viewModel.deleteCharacter(id = it.id) - if (screen.popBackStack().not()) { - window.closeWindows() - } + AnimatedContent( + targetState = viewModel.displayRollOverlay.value, + transitionSpec = { + val enter = fadeIn() + slideInVertically { 64 } + val exit = fadeOut() + slideOutVertically { 64 } + enter togetherWith exit + }, + ) { roll -> + when (roll) { + true -> RollPage( + viewModel = rollViewModel, + onDismissRequest = { + blurController.hide() + viewModel.hideRollOverlay() + }, + ) + + else -> Box( + modifier = Modifier.fillMaxSize() + ) } - }, - onDismissRequest = { - viewModel.hideConfirmCharacterDeletionDialog() - }, - ) - - CharacterSheetStatDialog( - dialog = viewModel.statChangeDialog, - onConfirm = { - viewModel.changeSubCharacteristic( - characteristicId = it.id, - value = it.value().text.toIntOrNull() ?: 0, - ) - viewModel.hideSubCharacteristicDialog() - }, - onDismissRequest = { - viewModel.hideSubCharacteristicDialog() } - ) + + CharacterSheetDeleteConfirmationDialog( + dialog = viewModel.displayDeleteConfirmationDialog, + onConfirm = { + scope.launch { + viewModel.deleteCharacter(id = it.id) + if (screen.popBackStack().not()) { + window.closeWindows() + } + } + }, + onDismissRequest = { + blurController.hide() + viewModel.hideConfirmCharacterDeletionDialog() + }, + ) + + CharacterSheetStatDialog( + dialog = viewModel.statChangeDialog, + onConfirm = { + viewModel.changeSubCharacteristic( + characteristicId = it.id, + value = it.value().text.toIntOrNull() ?: 0, + ) + viewModel.hideSubCharacteristicDialog() + }, + onDismissRequest = { + blurController.hide() + viewModel.hideSubCharacteristicDialog() + } + ) + } } @Composable diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt index 525731b..8134d14 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/CharacterSheetViewModel.kt @@ -17,6 +17,8 @@ import kotlinx.coroutines.runBlocking import kotlin.math.max import kotlin.math.min +private typealias CSDCDialogUio = CharacterSheetDeleteConfirmationDialogUio + class CharacterSheetViewModel( savedStateHandle: SavedStateHandle, ) : ViewModel() { @@ -25,10 +27,11 @@ class CharacterSheetViewModel( private val repository = CharacterSheetRepository private val factory = CharacterSheetFactory() - private val _displayDeleteConfirmationDialog = - mutableStateOf(null) - val displayDeleteConfirmationDialog: State - get() = _displayDeleteConfirmationDialog + private val _displayDeleteConfirmationDialog = mutableStateOf(null) + val displayDeleteConfirmationDialog: State get() = _displayDeleteConfirmationDialog + + private val _displayRollOverlay = mutableStateOf(false) + val displayRollOverlay: State get() = _displayRollOverlay private val _statChangeDialog = mutableStateOf(null) val statChangeDialog: State get() = _statChangeDialog @@ -140,4 +143,12 @@ class CharacterSheetViewModel( repository.save(it) } } + + fun showRollOverlay() { + _displayRollOverlay.value = true + } + + fun hideRollOverlay() { + _displayRollOverlay.value = false + } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetDeleteConfirmationDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetDeleteConfirmationDialog.kt index acf770d..83f6be1 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetDeleteConfirmationDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetDeleteConfirmationDialog.kt @@ -29,8 +29,8 @@ import androidx.compose.runtime.State import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp +import com.pixelized.desktop.lwa.theme.LwaColorPalette import lwacharactersheet.composeapp.generated.resources.Res import lwacharactersheet.composeapp.generated.resources.character_sheet__delete_dialog__cancel_action import lwacharactersheet.composeapp.generated.resources.character_sheet__delete_dialog__confirm_action @@ -38,8 +38,6 @@ import lwacharactersheet.composeapp.generated.resources.character_sheet__delete_ import lwacharactersheet.composeapp.generated.resources.character_sheet__delete_dialog__title import org.jetbrains.compose.resources.stringResource -private val DefaultScrimColor = Color.Black.copy(alpha = 0.6f) - @Stable data class CharacterSheetDeleteConfirmationDialogUio( val id: String, @@ -52,15 +50,6 @@ fun CharacterSheetDeleteConfirmationDialog( onConfirm: (CharacterSheetDeleteConfirmationDialogUio) -> Unit, onDismissRequest: () -> Unit, ) { - AnimatedVisibility( - visible = dialog.value != null, - ) { - Box( - modifier = Modifier - .fillMaxSize() - .background(color = DefaultScrimColor), - ) - } AnimatedContent( modifier = Modifier.fillMaxSize(), targetState = dialog.value, diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt index b99877e..59b467e 100644 --- a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/screen/characterSheet/detail/dialog/CharacterSheetStatDialog.kt @@ -1,14 +1,12 @@ package com.pixelized.desktop.lwa.screen.characterSheet.detail.dialog import androidx.compose.animation.AnimatedContent -import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.SizeTransform 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.background import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Arrangement @@ -33,15 +31,12 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.TextFieldValue import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp -private val DefaultScrimColor = Color.Black.copy(alpha = 0.6f) - @Stable data class StatChangeDialogUio( val id: String, @@ -57,15 +52,6 @@ fun CharacterSheetStatDialog( onConfirm: (StatChangeDialogUio) -> Unit, onDismissRequest: () -> Unit, ) { - AnimatedVisibility( - visible = dialog.value != null, - ) { - Box( - modifier = Modifier - .fillMaxSize() - .background(color = DefaultScrimColor), - ) - } AnimatedContent( modifier = Modifier.fillMaxSize(), targetState = dialog.value, @@ -140,7 +126,7 @@ private fun Dialog( }, singleLine = true, keyboardActions = KeyboardActions { onConfirm(dialog) }, - keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), + keyboardOptions = KeyboardOptions(imeAction = ImeAction.Done), placeholder = { dialog.placeholder }, onValueChange = dialog.onValueChange, ) diff --git a/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/theme/LwaColorPalette.kt b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/theme/LwaColorPalette.kt new file mode 100644 index 0000000..ca2525e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/pixelized/desktop/lwa/theme/LwaColorPalette.kt @@ -0,0 +1,7 @@ +package com.pixelized.desktop.lwa.theme + +import androidx.compose.ui.graphics.Color + +object LwaColorPalette { + val DefaultScrimColor = Color.Black.copy(alpha = 0.4f) +} \ No newline at end of file