Add animation to zap and reaction popups
This commit is contained in:
@@ -24,8 +24,10 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.compose.animation.AnimatedContent
|
import androidx.compose.animation.AnimatedContent
|
||||||
import androidx.compose.animation.AnimatedContentTransitionScope
|
import androidx.compose.animation.AnimatedContentTransitionScope
|
||||||
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.ContentTransform
|
import androidx.compose.animation.ContentTransform
|
||||||
import androidx.compose.animation.ExperimentalAnimationApi
|
import androidx.compose.animation.ExperimentalAnimationApi
|
||||||
|
import androidx.compose.animation.core.MutableTransitionState
|
||||||
import androidx.compose.animation.core.animateFloatAsState
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.animation.fadeIn
|
import androidx.compose.animation.fadeIn
|
||||||
@@ -147,6 +149,7 @@ import kotlinx.collections.immutable.persistentSetOf
|
|||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableSet
|
import kotlinx.collections.immutable.toImmutableSet
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@@ -1326,11 +1329,38 @@ fun ReactionChoicePopup(
|
|||||||
.collectAsStateWithLifecycle()
|
.collectAsStateWithLifecycle()
|
||||||
val toRemove = remember { baseNote.reactedBy(accountViewModel.userProfile()).toImmutableSet() }
|
val toRemove = remember { baseNote.reactedBy(accountViewModel.userProfile()).toImmutableSet() }
|
||||||
|
|
||||||
|
// Define animation specs
|
||||||
|
val animationDuration = 250
|
||||||
|
val fadeAnimationSpec = tween<Float>(durationMillis = animationDuration)
|
||||||
|
|
||||||
|
// Prevent multiple calls to onDismiss()
|
||||||
|
var dismissed by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val visibilityState = remember { MutableTransitionState(false).apply { targetState = true } }
|
||||||
|
LaunchedEffect(visibilityState.targetState) {
|
||||||
|
if (!visibilityState.targetState && !dismissed) {
|
||||||
|
delay(animationDuration.toLong())
|
||||||
|
dismissed = true
|
||||||
|
onDismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Popup(
|
Popup(
|
||||||
alignment = Alignment.BottomCenter,
|
alignment = Alignment.BottomCenter,
|
||||||
offset = IntOffset(0, iconSizePx),
|
offset = IntOffset(0, iconSizePx),
|
||||||
onDismissRequest = { onDismiss() },
|
onDismissRequest = { visibilityState.targetState = false },
|
||||||
properties = PopupProperties(focusable = true),
|
properties = PopupProperties(focusable = true),
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visibleState = visibilityState,
|
||||||
|
enter =
|
||||||
|
slideInVertically(
|
||||||
|
initialOffsetY = { it / 2 },
|
||||||
|
) + fadeIn(animationSpec = fadeAnimationSpec),
|
||||||
|
exit =
|
||||||
|
slideOutVertically(
|
||||||
|
targetOffsetY = { it / 2 },
|
||||||
|
) + fadeOut(animationSpec = fadeAnimationSpec),
|
||||||
) {
|
) {
|
||||||
ReactionChoicePopupContent(
|
ReactionChoicePopupContent(
|
||||||
reactions,
|
reactions,
|
||||||
@@ -1340,11 +1370,12 @@ fun ReactionChoicePopup(
|
|||||||
baseNote,
|
baseNote,
|
||||||
reactionType,
|
reactionType,
|
||||||
)
|
)
|
||||||
onDismiss()
|
visibilityState.targetState = false
|
||||||
},
|
},
|
||||||
onChangeAmount,
|
onChangeAmount,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalLayoutApi::class)
|
@OptIn(ExperimentalLayoutApi::class)
|
||||||
@@ -1505,11 +1536,38 @@ fun ZapAmountChoicePopup(
|
|||||||
|
|
||||||
val yOffset = with(LocalDensity.current) { -popupYOffset.toPx().toInt() }
|
val yOffset = with(LocalDensity.current) { -popupYOffset.toPx().toInt() }
|
||||||
|
|
||||||
|
// Define animation specs
|
||||||
|
val animationDuration = 250
|
||||||
|
val fadeAnimationSpec = tween<Float>(durationMillis = animationDuration)
|
||||||
|
|
||||||
|
// Prevent multiple calls to onDismiss()
|
||||||
|
var dismissed by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val visibilityState = remember { MutableTransitionState(false).apply { targetState = true } }
|
||||||
|
LaunchedEffect(visibilityState.targetState) {
|
||||||
|
if (!visibilityState.targetState && !dismissed) {
|
||||||
|
delay(animationDuration.toLong())
|
||||||
|
dismissed = true
|
||||||
|
onDismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Popup(
|
Popup(
|
||||||
alignment = Alignment.BottomCenter,
|
alignment = Alignment.BottomCenter,
|
||||||
offset = IntOffset(0, yOffset),
|
offset = IntOffset(0, yOffset),
|
||||||
onDismissRequest = { onDismiss() },
|
onDismissRequest = { visibilityState.targetState = false },
|
||||||
properties = PopupProperties(focusable = true),
|
properties = PopupProperties(focusable = true),
|
||||||
|
) {
|
||||||
|
AnimatedVisibility(
|
||||||
|
visibleState = visibilityState,
|
||||||
|
enter =
|
||||||
|
slideInVertically(
|
||||||
|
initialOffsetY = { it / 2 },
|
||||||
|
) + fadeIn(animationSpec = fadeAnimationSpec),
|
||||||
|
exit =
|
||||||
|
slideOutVertically(
|
||||||
|
targetOffsetY = { it / 2 },
|
||||||
|
) + fadeOut(animationSpec = fadeAnimationSpec),
|
||||||
) {
|
) {
|
||||||
FlowRow(horizontalArrangement = Arrangement.Center) {
|
FlowRow(horizontalArrangement = Arrangement.Center) {
|
||||||
zapAmountChoices.forEach { amountInSats ->
|
zapAmountChoices.forEach { amountInSats ->
|
||||||
@@ -1527,7 +1585,7 @@ fun ZapAmountChoicePopup(
|
|||||||
onProgress,
|
onProgress,
|
||||||
onPayViaIntent,
|
onPayViaIntent,
|
||||||
)
|
)
|
||||||
onDismiss()
|
visibilityState.targetState = false
|
||||||
},
|
},
|
||||||
shape = ButtonBorder,
|
shape = ButtonBorder,
|
||||||
colors =
|
colors =
|
||||||
@@ -1553,7 +1611,7 @@ fun ZapAmountChoicePopup(
|
|||||||
onProgress,
|
onProgress,
|
||||||
onPayViaIntent,
|
onPayViaIntent,
|
||||||
)
|
)
|
||||||
onDismiss()
|
visibilityState.targetState = false
|
||||||
},
|
},
|
||||||
onLongClick = { onChangeAmount() },
|
onLongClick = { onChangeAmount() },
|
||||||
),
|
),
|
||||||
@@ -1562,6 +1620,7 @@ fun ZapAmountChoicePopup(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showCount(count: Int?): String {
|
fun showCount(count: Int?): String {
|
||||||
|
|||||||
Reference in New Issue
Block a user