Change the blur mechanism
This commit is contained in:
parent
3705fbd947
commit
5ac0c2dcf6
7 changed files with 172 additions and 73 deletions
|
|
@ -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<Boolean> 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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<CharacterSheetDeleteConfirmationDialogUio?>(null)
|
||||
val displayDeleteConfirmationDialog: State<CharacterSheetDeleteConfirmationDialogUio?>
|
||||
get() = _displayDeleteConfirmationDialog
|
||||
private val _displayDeleteConfirmationDialog = mutableStateOf<CSDCDialogUio?>(null)
|
||||
val displayDeleteConfirmationDialog: State<CSDCDialogUio?> get() = _displayDeleteConfirmationDialog
|
||||
|
||||
private val _displayRollOverlay = mutableStateOf(false)
|
||||
val displayRollOverlay: State<Boolean> get() = _displayRollOverlay
|
||||
|
||||
private val _statChangeDialog = mutableStateOf<StatChangeDialogUio?>(null)
|
||||
val statChangeDialog: State<StatChangeDialogUio?> get() = _statChangeDialog
|
||||
|
|
@ -140,4 +143,12 @@ class CharacterSheetViewModel(
|
|||
repository.save(it)
|
||||
}
|
||||
}
|
||||
|
||||
fun showRollOverlay() {
|
||||
_displayRollOverlay.value = true
|
||||
}
|
||||
|
||||
fun hideRollOverlay() {
|
||||
_displayRollOverlay.value = false
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue