From f1d451c24c8b51e491caac7e9a05293bbc3f8314 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 11:22:11 -0300 Subject: [PATCH 01/16] feat: toast style v59 --- .../java/to/bitkit/ui/components/ToastView.kt | 44 +++++++------------ 1 file changed, 16 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index d9144e303..6484b155e 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -8,7 +8,6 @@ import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideOutVertically import androidx.compose.animation.togetherWith import androidx.compose.foundation.background -import androidx.compose.foundation.border import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -29,7 +28,6 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Brush.Companion.verticalGradient import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource @@ -47,7 +45,6 @@ fun ToastView( onDismiss: () -> Unit, ) { val tintColor = toast.tintColor() - val gradientColor = toast.gradientColor() Box( contentAlignment = Alignment.CenterStart, @@ -55,8 +52,7 @@ fun ToastView( .fillMaxWidth() .systemBarsPadding() .padding(horizontal = 16.dp) - .background(verticalGradient(listOf(gradientColor, Color.Black), startY = 0f), RoundedCornerShape(8.dp)) - .border(1.dp, tintColor, RoundedCornerShape(8.dp)) + .background(tintColor.copy(alpha = 0.32f), RoundedCornerShape(8.dp)) .padding(16.dp) .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { @@ -125,43 +121,46 @@ fun ToastOverlay( } } -@Preview(showBackground = true) +@Preview(showSystemUi = true) @Composable private fun ToastViewPreview() { AppThemeSurface { ScreenColumn( verticalArrangement = Arrangement.spacedBy(16.dp), ) { + ToastView( toast = Toast( - type = Toast.ToastType.SUCCESS, - title = "Success Toast", - description = "This is a toast message.", + type = Toast.ToastType.WARNING, + title = "You’re still offline", + description = "Check your connection to keep using Bitkit.", autoHide = true, ), onDismiss = {} ) ToastView( toast = Toast( - type = Toast.ToastType.INFO, - title = "Info Toast", - description = "This is a toast message.", - autoHide = false, + type = Toast.ToastType.LIGHTNING, + title = "Instant Payments Ready", + description = "You can now pay anyone, anywhere, instantly.", + autoHide = true, ), onDismiss = {} ) ToastView( toast = Toast( - type = Toast.ToastType.LIGHTNING, - title = "Lightning Toast", + type = Toast.ToastType.SUCCESS, + title = "You’re Back Online!", + description = "Successfully reconnected to the Internet.", autoHide = true, ), onDismiss = {} ) ToastView( toast = Toast( - type = Toast.ToastType.WARNING, - title = "Warning Toast", + type = Toast.ToastType.INFO, + title = "General Message", + description = "Used for neutral content to inform the user.", autoHide = false, ), onDismiss = {} @@ -179,17 +178,6 @@ private fun ToastViewPreview() { } } -@Suppress("MagicNumber") -@ReadOnlyComposable -@Composable -private fun Toast.gradientColor(): Color = when (type) { - Toast.ToastType.SUCCESS -> Color(0XFF1D2F1C) - Toast.ToastType.INFO -> Color(0XFF032E56) - Toast.ToastType.LIGHTNING -> Color(0XFF2B1637) - Toast.ToastType.WARNING -> Color(0XFF3C1001) - Toast.ToastType.ERROR -> Color(0XFF491F25) -} - @ReadOnlyComposable @Composable private fun Toast.tintColor(): Color = when (type) { From 01531363b71abe605e116286b3acb23595974f04 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 11:32:37 -0300 Subject: [PATCH 02/16] feat: shape --- app/src/main/java/to/bitkit/ui/components/ToastView.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 6484b155e..c8853e056 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -19,11 +19,11 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Close import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable import androidx.compose.ui.Alignment @@ -52,7 +52,7 @@ fun ToastView( .fillMaxWidth() .systemBarsPadding() .padding(horizontal = 16.dp) - .background(tintColor.copy(alpha = 0.32f), RoundedCornerShape(8.dp)) + .background(tintColor.copy(alpha = 0.32f), shape = MaterialTheme.shapes.medium) .padding(16.dp) .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { From 182e01f332902333846bb9cb83439b3e4725a4ea Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 12:02:19 -0300 Subject: [PATCH 03/16] feat: background blur --- .../java/to/bitkit/ui/components/ToastView.kt | 166 ++++++++++++++++-- 1 file changed, 149 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index c8853e056..b4048fcf1 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -2,20 +2,23 @@ package to.bitkit.ui.components import androidx.compose.animation.AnimatedContent import androidx.compose.animation.SizeTransform +import androidx.compose.animation.core.Animatable +import androidx.compose.animation.core.Spring +import androidx.compose.animation.core.spring +import androidx.compose.animation.core.tween 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.gestures.detectDragGestures 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.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBarsPadding @@ -26,59 +29,174 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.ReadOnlyComposable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.shadow import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.platform.testTag import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import kotlinx.coroutines.launch import to.bitkit.R import to.bitkit.models.Toast import to.bitkit.ui.scaffold.ScreenColumn import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors +import kotlin.math.roundToInt @Composable fun ToastView( toast: Toast, onDismiss: () -> Unit, + onDragStart: () -> Unit = {}, + onDragEnd: () -> Unit = {}, ) { val tintColor = toast.tintColor() + val coroutineScope = rememberCoroutineScope() + val dragOffset = remember { Animatable(0f) } + var hasPausedAutoHide by remember { mutableStateOf(false) } + val dismissThreshold = 50.dp Box( - contentAlignment = Alignment.CenterStart, + contentAlignment = Alignment.TopStart, modifier = Modifier .fillMaxWidth() .systemBarsPadding() .padding(horizontal = 16.dp) - .background(tintColor.copy(alpha = 0.32f), shape = MaterialTheme.shapes.medium) - .padding(16.dp) .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.fillMaxWidth() + // Main toast content + Box( + modifier = Modifier + .fillMaxWidth() + .offset { IntOffset(0, dragOffset.value.roundToInt()) } + .shadow( + elevation = 10.dp, + shape = MaterialTheme.shapes.medium, + ambientColor = Color.Black.copy(alpha = 0.4f), + spotColor = Color.Black.copy(alpha = 0.4f) + ) + .background( + color = MaterialTheme.colorScheme.surface.copy(alpha = 0.85f), + shape = MaterialTheme.shapes.medium + ) + .background( + color = tintColor.copy(alpha = 0.32f), + shape = MaterialTheme.shapes.medium + ) + .pointerInput(Unit) { + detectDragGestures( + onDragStart = { + // Drag started + }, + onDragEnd = { + // Resume auto-hide when drag ends (if we paused it) + if (hasPausedAutoHide) { + hasPausedAutoHide = false + onDragEnd() + } + + coroutineScope.launch { + // Dismiss if swiped up enough, otherwise snap back + if (dragOffset.value < -dismissThreshold.toPx()) { + // Animate out + dragOffset.animateTo( + targetValue = -200f, + animationSpec = tween(durationMillis = 300) + ) + onDismiss() + } else { + // Snap back to original position + dragOffset.animateTo( + targetValue = 0f, + animationSpec = spring( + dampingRatio = 0.7f, + stiffness = Spring.StiffnessMedium + ) + ) + } + } + }, + onDragCancel = { + coroutineScope.launch { + dragOffset.animateTo( + targetValue = 0f, + animationSpec = spring( + dampingRatio = 0.7f, + stiffness = Spring.StiffnessMedium + ) + ) + } + }, + onDrag = { change, dragAmount -> + change.consume() + coroutineScope.launch { + val translation = dragOffset.value + dragAmount.y + + if (translation < 0) { + // Upward drag - allow freely + dragOffset.snapTo(translation) + } else { + // Downward drag - apply resistance + dragOffset.snapTo(translation * 0.08f) + } + + // Pause auto-hide when drag starts (only once) + if (kotlin.math.abs(dragOffset.value) > 5 && !hasPausedAutoHide) { + hasPausedAutoHide = true + onDragStart() + } + } + } + ) + } ) { - Column(modifier = Modifier.weight(1f)) { + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { BodyMSB( text = toast.title, color = tintColor, ) toast.description?.let { description -> - Spacer(modifier = Modifier.height(8.dp)) - Caption(text = description) + Caption( + text = description, + color = MaterialTheme.colorScheme.onSurface + ) } } - if (!toast.autoHide) { + } + + // Close button overlay (top-trailing) + if (!toast.autoHide) { + Box( + modifier = Modifier + .fillMaxWidth() + .offset { IntOffset(0, dragOffset.value.roundToInt()) }, + contentAlignment = Alignment.TopEnd + ) { IconButton( onClick = onDismiss, - modifier = Modifier.size(24.dp) + modifier = Modifier + .size(48.dp) + .padding(16.dp) ) { Icon( imageVector = Icons.Default.Close, contentDescription = stringResource(R.string.common__close), - tint = Color.White, + tint = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(16.dp) ) } } @@ -90,6 +208,8 @@ fun ToastView( private fun ToastHost( toast: Toast?, onDismiss: () -> Unit, + onDragStart: () -> Unit = {}, + onDragEnd: () -> Unit = {}, ) { AnimatedContent( targetState = toast, @@ -102,7 +222,12 @@ private fun ToastHost( label = "toastAnimation", ) { if (it != null) { - ToastView(toast = it, onDismiss = onDismiss) + ToastView( + toast = it, + onDismiss = onDismiss, + onDragStart = onDragStart, + onDragEnd = onDragEnd + ) } } } @@ -112,12 +237,19 @@ fun ToastOverlay( toast: Toast?, modifier: Modifier = Modifier, onDismiss: () -> Unit, + onDragStart: () -> Unit = {}, + onDragEnd: () -> Unit = {}, ) { Box( contentAlignment = Alignment.TopCenter, modifier = modifier.fillMaxSize(), ) { - ToastHost(toast = toast, onDismiss = onDismiss) + ToastHost( + toast = toast, + onDismiss = onDismiss, + onDragStart = onDragStart, + onDragEnd = onDragEnd + ) } } From 3108eb955b7788a683fa6c9db228e2c737cb1781 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 12:15:40 -0300 Subject: [PATCH 04/16] feat: haze state --- .../java/to/bitkit/ui/components/ToastView.kt | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index b4048fcf1..aac2e4680 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -44,6 +44,11 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import dev.chrisbanes.haze.HazeState +import dev.chrisbanes.haze.hazeEffect +import dev.chrisbanes.haze.materials.CupertinoMaterials +import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi +import dev.chrisbanes.haze.rememberHazeState import kotlinx.coroutines.launch import to.bitkit.R import to.bitkit.models.Toast @@ -52,10 +57,12 @@ import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import kotlin.math.roundToInt +@OptIn(ExperimentalHazeMaterialsApi::class) @Composable fun ToastView( toast: Toast, onDismiss: () -> Unit, + hazeState: HazeState = rememberHazeState(blurEnabled = true), onDragStart: () -> Unit = {}, onDragEnd: () -> Unit = {}, ) { @@ -74,6 +81,11 @@ fun ToastView( .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { // Main toast content + val backgroundAlpha = 0.7f + val toastMaterial = CupertinoMaterials.ultraThin( + containerColor = MaterialTheme.colorScheme.surface.copy(alpha = backgroundAlpha) + ) + Box( modifier = Modifier .fillMaxWidth() @@ -85,9 +97,15 @@ fun ToastView( spotColor = Color.Black.copy(alpha = 0.4f) ) .background( - color = MaterialTheme.colorScheme.surface.copy(alpha = 0.85f), + color = MaterialTheme.colorScheme.surface.copy(alpha = backgroundAlpha), shape = MaterialTheme.shapes.medium ) + .then( + Modifier.hazeEffect( + state = hazeState, + style = toastMaterial + ) + ) .background( color = tintColor.copy(alpha = 0.32f), shape = MaterialTheme.shapes.medium @@ -207,6 +225,7 @@ fun ToastView( @Composable private fun ToastHost( toast: Toast?, + hazeState: HazeState, onDismiss: () -> Unit, onDragStart: () -> Unit = {}, onDragEnd: () -> Unit = {}, @@ -225,6 +244,7 @@ private fun ToastHost( ToastView( toast = it, onDismiss = onDismiss, + hazeState = hazeState, onDragStart = onDragStart, onDragEnd = onDragEnd ) @@ -236,6 +256,7 @@ private fun ToastHost( fun ToastOverlay( toast: Toast?, modifier: Modifier = Modifier, + hazeState: HazeState = rememberHazeState(blurEnabled = true), onDismiss: () -> Unit, onDragStart: () -> Unit = {}, onDragEnd: () -> Unit = {}, @@ -246,6 +267,7 @@ fun ToastOverlay( ) { ToastHost( toast = toast, + hazeState = hazeState, onDismiss = onDismiss, onDragStart = onDragStart, onDragEnd = onDragEnd @@ -264,11 +286,11 @@ private fun ToastViewPreview() { ToastView( toast = Toast( type = Toast.ToastType.WARNING, - title = "You’re still offline", + title = "You're still offline", description = "Check your connection to keep using Bitkit.", autoHide = true, ), - onDismiss = {} + onDismiss = {}, ) ToastView( toast = Toast( @@ -277,16 +299,16 @@ private fun ToastViewPreview() { description = "You can now pay anyone, anywhere, instantly.", autoHide = true, ), - onDismiss = {} + onDismiss = {}, ) ToastView( toast = Toast( type = Toast.ToastType.SUCCESS, - title = "You’re Back Online!", + title = "You're Back Online!", description = "Successfully reconnected to the Internet.", autoHide = true, ), - onDismiss = {} + onDismiss = {}, ) ToastView( toast = Toast( @@ -295,7 +317,7 @@ private fun ToastViewPreview() { description = "Used for neutral content to inform the user.", autoHide = false, ), - onDismiss = {} + onDismiss = {}, ) ToastView( toast = Toast( @@ -304,7 +326,7 @@ private fun ToastViewPreview() { description = "This is a toast message.", autoHide = true, ), - onDismiss = {} + onDismiss = {}, ) } } From 86bf87a8b72d11c0c8e8a9a9781bcbf8396289dd Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 12:35:36 -0300 Subject: [PATCH 05/16] feat: haze state --- app/src/main/java/to/bitkit/ui/components/ToastView.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index aac2e4680..ac2aba01a 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -81,10 +81,9 @@ fun ToastView( .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { // Main toast content - val backgroundAlpha = 0.7f - val toastMaterial = CupertinoMaterials.ultraThin( - containerColor = MaterialTheme.colorScheme.surface.copy(alpha = backgroundAlpha) - ) + // Match TabBar pattern: opaque base + hazeEffect + tint overlay + val containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f) + val toastMaterial = CupertinoMaterials.ultraThin(containerColor = containerColor) Box( modifier = Modifier @@ -97,7 +96,7 @@ fun ToastView( spotColor = Color.Black.copy(alpha = 0.4f) ) .background( - color = MaterialTheme.colorScheme.surface.copy(alpha = backgroundAlpha), + color = containerColor, shape = MaterialTheme.shapes.medium ) .then( From e4ea63b1d5c238383e6872b2a86af602c04a50f3 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 12:53:06 -0300 Subject: [PATCH 06/16] chore: lift up haze state --- app/src/main/java/to/bitkit/ui/ContentView.kt | 2 +- app/src/main/java/to/bitkit/ui/MainActivity.kt | 4 ++++ app/src/main/java/to/bitkit/ui/components/ToastView.kt | 5 ++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 1375eb400..752f880f1 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -193,6 +193,7 @@ fun ContentView( transferViewModel: TransferViewModel, settingsViewModel: SettingsViewModel, backupsViewModel: BackupsViewModel, + hazeState: dev.chrisbanes.haze.HazeState, modifier: Modifier = Modifier, ) { val navController = rememberNavController() @@ -351,7 +352,6 @@ fun ContentView( val hasSeenShopIntro by settingsViewModel.hasSeenShopIntro.collectAsStateWithLifecycle() val currentSheet by appViewModel.currentSheet.collectAsStateWithLifecycle() - val hazeState = rememberHazeState() Box( modifier = modifier.fillMaxSize() diff --git a/app/src/main/java/to/bitkit/ui/MainActivity.kt b/app/src/main/java/to/bitkit/ui/MainActivity.kt index 9760415a2..5bac78b2f 100644 --- a/app/src/main/java/to/bitkit/ui/MainActivity.kt +++ b/app/src/main/java/to/bitkit/ui/MainActivity.kt @@ -15,6 +15,7 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId +import dev.chrisbanes.haze.rememberHazeState import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.fragment.app.FragmentActivity import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -96,6 +97,7 @@ class MainActivity : FragmentActivity() { val walletExists by walletViewModel.walletState .map { it.walletExists } .collectAsStateWithLifecycle(initialValue = walletViewModel.walletExists) + val hazeState = rememberHazeState(blurEnabled = true) LaunchedEffect( walletExists, @@ -128,6 +130,7 @@ class MainActivity : FragmentActivity() { transferViewModel = transferViewModel, settingsViewModel = settingsViewModel, backupsViewModel = backupsViewModel, + hazeState = hazeState, ) } @@ -164,6 +167,7 @@ class MainActivity : FragmentActivity() { ToastOverlay( toast = appViewModel.currentToast, + hazeState = hazeState, onDismiss = { appViewModel.hideToast() } diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index ac2aba01a..b9b09eedc 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -81,9 +81,8 @@ fun ToastView( .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { // Main toast content - // Match TabBar pattern: opaque base + hazeEffect + tint overlay - val containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.95f) - val toastMaterial = CupertinoMaterials.ultraThin(containerColor = containerColor) + val containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.9f) + val toastMaterial = CupertinoMaterials.thin(containerColor = containerColor) Box( modifier = Modifier From c5ef1125df6843f621dbdc310b192374ca7b1564 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 15:09:28 -0300 Subject: [PATCH 07/16] feat: set haze source --- app/src/main/java/to/bitkit/ui/MainActivity.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/to/bitkit/ui/MainActivity.kt b/app/src/main/java/to/bitkit/ui/MainActivity.kt index 5bac78b2f..961636e3a 100644 --- a/app/src/main/java/to/bitkit/ui/MainActivity.kt +++ b/app/src/main/java/to/bitkit/ui/MainActivity.kt @@ -25,6 +25,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute import dagger.hilt.android.AndroidEntryPoint +import dev.chrisbanes.haze.hazeSource import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -131,6 +132,7 @@ class MainActivity : FragmentActivity() { settingsViewModel = settingsViewModel, backupsViewModel = backupsViewModel, hazeState = hazeState, + modifier = Modifier.hazeSource(hazeState, zIndex = 0f) ) } From a2e0a048f1d106797044b13b8352510cbde0020c Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 15:23:32 -0300 Subject: [PATCH 08/16] chore: code cleanup --- .../java/to/bitkit/ui/components/ToastView.kt | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index b9b09eedc..05dec76dd 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -81,8 +81,7 @@ fun ToastView( .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { // Main toast content - val containerColor = MaterialTheme.colorScheme.surface.copy(alpha = 0.9f) - val toastMaterial = CupertinoMaterials.thin(containerColor = containerColor) + val toastMaterial = CupertinoMaterials.thin(containerColor = tintColor) Box( modifier = Modifier @@ -94,15 +93,9 @@ fun ToastView( ambientColor = Color.Black.copy(alpha = 0.4f), spotColor = Color.Black.copy(alpha = 0.4f) ) - .background( - color = containerColor, - shape = MaterialTheme.shapes.medium - ) - .then( - Modifier.hazeEffect( - state = hazeState, - style = toastMaterial - ) + .hazeEffect( + state = hazeState, + style = toastMaterial ) .background( color = tintColor.copy(alpha = 0.32f), @@ -188,7 +181,7 @@ fun ToastView( toast.description?.let { description -> Caption( text = description, - color = MaterialTheme.colorScheme.onSurface + color = Colors.White ) } } From 5bd380a0160d87473fead719a22e9f98fd883dbd Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Fri, 5 Dec 2025 17:37:44 -0300 Subject: [PATCH 09/16] chore: remove state injection --- app/src/main/java/to/bitkit/ui/ContentView.kt | 2 +- app/src/main/java/to/bitkit/ui/MainActivity.kt | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 752f880f1..1375eb400 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -193,7 +193,6 @@ fun ContentView( transferViewModel: TransferViewModel, settingsViewModel: SettingsViewModel, backupsViewModel: BackupsViewModel, - hazeState: dev.chrisbanes.haze.HazeState, modifier: Modifier = Modifier, ) { val navController = rememberNavController() @@ -352,6 +351,7 @@ fun ContentView( val hasSeenShopIntro by settingsViewModel.hasSeenShopIntro.collectAsStateWithLifecycle() val currentSheet by appViewModel.currentSheet.collectAsStateWithLifecycle() + val hazeState = rememberHazeState() Box( modifier = modifier.fillMaxSize() diff --git a/app/src/main/java/to/bitkit/ui/MainActivity.kt b/app/src/main/java/to/bitkit/ui/MainActivity.kt index 961636e3a..9c55f34e2 100644 --- a/app/src/main/java/to/bitkit/ui/MainActivity.kt +++ b/app/src/main/java/to/bitkit/ui/MainActivity.kt @@ -15,7 +15,6 @@ import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.semantics import androidx.compose.ui.semantics.testTagsAsResourceId -import dev.chrisbanes.haze.rememberHazeState import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.fragment.app.FragmentActivity import androidx.lifecycle.compose.collectAsStateWithLifecycle @@ -26,6 +25,7 @@ import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute import dagger.hilt.android.AndroidEntryPoint import dev.chrisbanes.haze.hazeSource +import dev.chrisbanes.haze.rememberHazeState import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @@ -131,7 +131,6 @@ class MainActivity : FragmentActivity() { transferViewModel = transferViewModel, settingsViewModel = settingsViewModel, backupsViewModel = backupsViewModel, - hazeState = hazeState, modifier = Modifier.hazeSource(hazeState, zIndex = 0f) ) } From 4d20ac210b40e68604a1f1985a0a41466d8bf6ba Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 06:43:26 -0300 Subject: [PATCH 10/16] chore: lint --- app/src/main/java/to/bitkit/ui/components/ToastView.kt | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 05dec76dd..05d121079 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -103,9 +103,6 @@ fun ToastView( ) .pointerInput(Unit) { detectDragGestures( - onDragStart = { - // Drag started - }, onDragEnd = { // Resume auto-hide when drag ends (if we paused it) if (hasPausedAutoHide) { From e57c1017ccf8bd1cc55b1b7dc591c9b4854f11ef Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 06:50:13 -0300 Subject: [PATCH 11/16] chore: extract magic numbers --- .../java/to/bitkit/ui/components/ToastView.kt | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 05d121079..601ef79cc 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -57,6 +57,16 @@ import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import kotlin.math.roundToInt +private const val DISMISS_THRESHOLD_DP = 50 +private const val DISMISS_ANIMATION_TARGET_PX = -200f +private const val DISMISS_ANIMATION_DURATION_MS = 300 +private const val SNAP_BACK_DAMPING_RATIO = 0.7f +private const val DRAG_RESISTANCE_FACTOR = 0.08f +private const val DRAG_START_THRESHOLD_PX = 5 +private const val TINT_ALPHA = 0.32f +private const val SHADOW_ALPHA = 0.4f +private const val ELEVATION_DP = 10 + @OptIn(ExperimentalHazeMaterialsApi::class) @Composable fun ToastView( @@ -70,7 +80,7 @@ fun ToastView( val coroutineScope = rememberCoroutineScope() val dragOffset = remember { Animatable(0f) } var hasPausedAutoHide by remember { mutableStateOf(false) } - val dismissThreshold = 50.dp + val dismissThreshold = DISMISS_THRESHOLD_DP.dp Box( contentAlignment = Alignment.TopStart, @@ -88,17 +98,17 @@ fun ToastView( .fillMaxWidth() .offset { IntOffset(0, dragOffset.value.roundToInt()) } .shadow( - elevation = 10.dp, + elevation = ELEVATION_DP.dp, shape = MaterialTheme.shapes.medium, - ambientColor = Color.Black.copy(alpha = 0.4f), - spotColor = Color.Black.copy(alpha = 0.4f) + ambientColor = Color.Black.copy(alpha = SHADOW_ALPHA), + spotColor = Color.Black.copy(alpha = SHADOW_ALPHA) ) .hazeEffect( state = hazeState, style = toastMaterial ) .background( - color = tintColor.copy(alpha = 0.32f), + color = tintColor.copy(alpha = TINT_ALPHA), shape = MaterialTheme.shapes.medium ) .pointerInput(Unit) { @@ -115,8 +125,8 @@ fun ToastView( if (dragOffset.value < -dismissThreshold.toPx()) { // Animate out dragOffset.animateTo( - targetValue = -200f, - animationSpec = tween(durationMillis = 300) + targetValue = DISMISS_ANIMATION_TARGET_PX, + animationSpec = tween(durationMillis = DISMISS_ANIMATION_DURATION_MS) ) onDismiss() } else { @@ -124,7 +134,7 @@ fun ToastView( dragOffset.animateTo( targetValue = 0f, animationSpec = spring( - dampingRatio = 0.7f, + dampingRatio = SNAP_BACK_DAMPING_RATIO, stiffness = Spring.StiffnessMedium ) ) @@ -136,7 +146,7 @@ fun ToastView( dragOffset.animateTo( targetValue = 0f, animationSpec = spring( - dampingRatio = 0.7f, + dampingRatio = SNAP_BACK_DAMPING_RATIO, stiffness = Spring.StiffnessMedium ) ) @@ -152,11 +162,11 @@ fun ToastView( dragOffset.snapTo(translation) } else { // Downward drag - apply resistance - dragOffset.snapTo(translation * 0.08f) + dragOffset.snapTo(translation * DRAG_RESISTANCE_FACTOR) } // Pause auto-hide when drag starts (only once) - if (kotlin.math.abs(dragOffset.value) > 5 && !hasPausedAutoHide) { + if (kotlin.math.abs(dragOffset.value) > DRAG_START_THRESHOLD_PX && !hasPausedAutoHide) { hasPausedAutoHide = true onDragStart() } From 245b53fcdca1f2fc1bbafbe0694257921d198b85 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 14:27:49 -0300 Subject: [PATCH 12/16] chore: hoist haze style --- app/src/main/java/to/bitkit/ui/components/ToastView.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 601ef79cc..eb3c04d82 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -45,6 +45,7 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp import dev.chrisbanes.haze.HazeState +import dev.chrisbanes.haze.HazeStyle import dev.chrisbanes.haze.hazeEffect import dev.chrisbanes.haze.materials.CupertinoMaterials import dev.chrisbanes.haze.materials.ExperimentalHazeMaterialsApi @@ -73,6 +74,7 @@ fun ToastView( toast: Toast, onDismiss: () -> Unit, hazeState: HazeState = rememberHazeState(blurEnabled = true), + hazeStyle: HazeStyle = CupertinoMaterials.thin(containerColor = toast.tintColor()), onDragStart: () -> Unit = {}, onDragEnd: () -> Unit = {}, ) { @@ -90,8 +92,6 @@ fun ToastView( .padding(horizontal = 16.dp) .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { - // Main toast content - val toastMaterial = CupertinoMaterials.thin(containerColor = tintColor) Box( modifier = Modifier @@ -105,7 +105,7 @@ fun ToastView( ) .hazeEffect( state = hazeState, - style = toastMaterial + style = hazeStyle ) .background( color = tintColor.copy(alpha = TINT_ALPHA), From 0765eb4471ad1da2291f06fc8d803b5578caf19b Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 14:28:46 -0300 Subject: [PATCH 13/16] chore: add modifier parameter --- app/src/main/java/to/bitkit/ui/components/ToastView.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index eb3c04d82..5a1530dcd 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -73,6 +73,7 @@ private const val ELEVATION_DP = 10 fun ToastView( toast: Toast, onDismiss: () -> Unit, + modifier: Modifier = Modifier, hazeState: HazeState = rememberHazeState(blurEnabled = true), hazeStyle: HazeStyle = CupertinoMaterials.thin(containerColor = toast.tintColor()), onDragStart: () -> Unit = {}, @@ -86,7 +87,7 @@ fun ToastView( Box( contentAlignment = Alignment.TopStart, - modifier = Modifier + modifier = modifier .fillMaxWidth() .systemBarsPadding() .padding(horizontal = 16.dp) From 3a05d4779587d5453c4fa6408e7e0ec988caeaf2 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 14:42:35 -0300 Subject: [PATCH 14/16] feat: add horizontal swipe detector --- .../java/to/bitkit/ui/components/ToastView.kt | 97 ++++++++++++++----- 1 file changed, 73 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 5a1530dcd..8da981097 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -64,6 +64,7 @@ private const val DISMISS_ANIMATION_DURATION_MS = 300 private const val SNAP_BACK_DAMPING_RATIO = 0.7f private const val DRAG_RESISTANCE_FACTOR = 0.08f private const val DRAG_START_THRESHOLD_PX = 5 +private const val HORIZONTAL_DISMISS_ANIMATION_TARGET_PX = 500f private const val TINT_ALPHA = 0.32f private const val SHADOW_ALPHA = 0.4f private const val ELEVATION_DP = 10 @@ -81,7 +82,8 @@ fun ToastView( ) { val tintColor = toast.tintColor() val coroutineScope = rememberCoroutineScope() - val dragOffset = remember { Animatable(0f) } + val dragOffsetY = remember { Animatable(0f) } + val dragOffsetX = remember { Animatable(0f) } var hasPausedAutoHide by remember { mutableStateOf(false) } val dismissThreshold = DISMISS_THRESHOLD_DP.dp @@ -97,7 +99,7 @@ fun ToastView( Box( modifier = Modifier .fillMaxWidth() - .offset { IntOffset(0, dragOffset.value.roundToInt()) } + .offset { IntOffset(dragOffsetX.value.roundToInt(), dragOffsetY.value.roundToInt()) } .shadow( elevation = ELEVATION_DP.dp, shape = MaterialTheme.shapes.medium, @@ -122,17 +124,58 @@ fun ToastView( } coroutineScope.launch { - // Dismiss if swiped up enough, otherwise snap back - if (dragOffset.value < -dismissThreshold.toPx()) { - // Animate out - dragOffset.animateTo( + val horizontalSwipeDistance = kotlin.math.abs(dragOffsetX.value) + val verticalSwipeDistance = kotlin.math.abs(dragOffsetY.value) + + // Determine if this is primarily horizontal or vertical swipe + val isHorizontalSwipe = horizontalSwipeDistance > verticalSwipeDistance + + if (isHorizontalSwipe && horizontalSwipeDistance > dismissThreshold.toPx()) { + // Horizontal swipe dismiss - animate out in swipe direction + val targetX = if (dragOffsetX.value > 0) { + HORIZONTAL_DISMISS_ANIMATION_TARGET_PX + } else { + -HORIZONTAL_DISMISS_ANIMATION_TARGET_PX + } + dragOffsetX.animateTo( + targetValue = targetX, + animationSpec = tween(durationMillis = DISMISS_ANIMATION_DURATION_MS) + ) + onDismiss() + } else if (!isHorizontalSwipe && dragOffsetY.value < -dismissThreshold.toPx()) { + // Vertical swipe up dismiss - animate out upward + dragOffsetY.animateTo( targetValue = DISMISS_ANIMATION_TARGET_PX, animationSpec = tween(durationMillis = DISMISS_ANIMATION_DURATION_MS) ) onDismiss() } else { // Snap back to original position - dragOffset.animateTo( + launch { + dragOffsetX.animateTo( + targetValue = 0f, + animationSpec = spring( + dampingRatio = SNAP_BACK_DAMPING_RATIO, + stiffness = Spring.StiffnessMedium + ) + ) + } + launch { + dragOffsetY.animateTo( + targetValue = 0f, + animationSpec = spring( + dampingRatio = SNAP_BACK_DAMPING_RATIO, + stiffness = Spring.StiffnessMedium + ) + ) + } + } + } + }, + onDragCancel = { + coroutineScope.launch { + launch { + dragOffsetX.animateTo( targetValue = 0f, animationSpec = spring( dampingRatio = SNAP_BACK_DAMPING_RATIO, @@ -140,34 +183,40 @@ fun ToastView( ) ) } - } - }, - onDragCancel = { - coroutineScope.launch { - dragOffset.animateTo( - targetValue = 0f, - animationSpec = spring( - dampingRatio = SNAP_BACK_DAMPING_RATIO, - stiffness = Spring.StiffnessMedium + launch { + dragOffsetY.animateTo( + targetValue = 0f, + animationSpec = spring( + dampingRatio = SNAP_BACK_DAMPING_RATIO, + stiffness = Spring.StiffnessMedium + ) ) - ) + } } }, onDrag = { change, dragAmount -> change.consume() coroutineScope.launch { - val translation = dragOffset.value + dragAmount.y - - if (translation < 0) { + // Handle vertical drag + val translationY = dragOffsetY.value + dragAmount.y + if (translationY < 0) { // Upward drag - allow freely - dragOffset.snapTo(translation) + dragOffsetY.snapTo(translationY) } else { // Downward drag - apply resistance - dragOffset.snapTo(translation * DRAG_RESISTANCE_FACTOR) + dragOffsetY.snapTo(translationY * DRAG_RESISTANCE_FACTOR) } + // Handle horizontal drag - allow freely in both directions + val translationX = dragOffsetX.value + dragAmount.x + dragOffsetX.snapTo(translationX) + // Pause auto-hide when drag starts (only once) - if (kotlin.math.abs(dragOffset.value) > DRAG_START_THRESHOLD_PX && !hasPausedAutoHide) { + val totalDragDistance = kotlin.math.sqrt( + dragOffsetX.value * dragOffsetX.value + + dragOffsetY.value * dragOffsetY.value + ) + if (totalDragDistance > DRAG_START_THRESHOLD_PX && !hasPausedAutoHide) { hasPausedAutoHide = true onDragStart() } @@ -200,7 +249,7 @@ fun ToastView( Box( modifier = Modifier .fillMaxWidth() - .offset { IntOffset(0, dragOffset.value.roundToInt()) }, + .offset { IntOffset(dragOffsetX.value.roundToInt(), dragOffsetY.value.roundToInt()) }, contentAlignment = Alignment.TopEnd ) { IconButton( From ce801753204fa49c95d7f438db614ab4cec6cc18 Mon Sep 17 00:00:00 2001 From: jvsena42 Date: Mon, 8 Dec 2025 14:50:15 -0300 Subject: [PATCH 15/16] fix: remove extra dismiss animation --- .../java/to/bitkit/ui/components/ToastView.kt | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/to/bitkit/ui/components/ToastView.kt b/app/src/main/java/to/bitkit/ui/components/ToastView.kt index 8da981097..ab52a81d9 100644 --- a/app/src/main/java/to/bitkit/ui/components/ToastView.kt +++ b/app/src/main/java/to/bitkit/ui/components/ToastView.kt @@ -5,7 +5,6 @@ import androidx.compose.animation.SizeTransform import androidx.compose.animation.core.Animatable import androidx.compose.animation.core.Spring import androidx.compose.animation.core.spring -import androidx.compose.animation.core.tween import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.animation.slideInVertically @@ -58,13 +57,10 @@ import to.bitkit.ui.theme.AppThemeSurface import to.bitkit.ui.theme.Colors import kotlin.math.roundToInt -private const val DISMISS_THRESHOLD_DP = 50 -private const val DISMISS_ANIMATION_TARGET_PX = -200f -private const val DISMISS_ANIMATION_DURATION_MS = 300 +private const val DISMISS_THRESHOLD_DP = 40 private const val SNAP_BACK_DAMPING_RATIO = 0.7f private const val DRAG_RESISTANCE_FACTOR = 0.08f private const val DRAG_START_THRESHOLD_PX = 5 -private const val HORIZONTAL_DISMISS_ANIMATION_TARGET_PX = 500f private const val TINT_ALPHA = 0.32f private const val SHADOW_ALPHA = 0.4f private const val ELEVATION_DP = 10 @@ -95,7 +91,6 @@ fun ToastView( .padding(horizontal = 16.dp) .then(toast.testTag?.let { Modifier.testTag(it) } ?: Modifier), ) { - Box( modifier = Modifier .fillMaxWidth() @@ -131,23 +126,10 @@ fun ToastView( val isHorizontalSwipe = horizontalSwipeDistance > verticalSwipeDistance if (isHorizontalSwipe && horizontalSwipeDistance > dismissThreshold.toPx()) { - // Horizontal swipe dismiss - animate out in swipe direction - val targetX = if (dragOffsetX.value > 0) { - HORIZONTAL_DISMISS_ANIMATION_TARGET_PX - } else { - -HORIZONTAL_DISMISS_ANIMATION_TARGET_PX - } - dragOffsetX.animateTo( - targetValue = targetX, - animationSpec = tween(durationMillis = DISMISS_ANIMATION_DURATION_MS) - ) + // Horizontal swipe dismiss onDismiss() } else if (!isHorizontalSwipe && dragOffsetY.value < -dismissThreshold.toPx()) { - // Vertical swipe up dismiss - animate out upward - dragOffsetY.animateTo( - targetValue = DISMISS_ANIMATION_TARGET_PX, - animationSpec = tween(durationMillis = DISMISS_ANIMATION_DURATION_MS) - ) + // Vertical swipe up dismiss onDismiss() } else { // Snap back to original position @@ -214,7 +196,7 @@ fun ToastView( // Pause auto-hide when drag starts (only once) val totalDragDistance = kotlin.math.sqrt( dragOffsetX.value * dragOffsetX.value + - dragOffsetY.value * dragOffsetY.value + dragOffsetY.value * dragOffsetY.value ) if (totalDragDistance > DRAG_START_THRESHOLD_PX && !hasPausedAutoHide) { hasPausedAutoHide = true From 0a25d0a824f24b511add11973962b90585493a28 Mon Sep 17 00:00:00 2001 From: Piotr Stachyra Date: Mon, 8 Dec 2025 11:11:16 +0100 Subject: [PATCH 16/16] SpendingBalanceReadyToast --- app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt index 0043d3be4..05a64123e 100644 --- a/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt +++ b/app/src/main/java/to/bitkit/viewmodels/AppViewModel.kt @@ -333,6 +333,7 @@ class AppViewModel @Inject constructor( type = Toast.ToastType.LIGHTNING, title = context.getString(R.string.lightning__channel_opened_title), description = context.getString(R.string.lightning__channel_opened_msg), + testTag = "SpendingBalanceReadyToast", ) }