diff --git a/.gitignore b/.gitignore index 7f1d0cfdd..07a92eda3 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ .externalNativeBuild .cxx local.properties +.cursor # Secrets google-services.json diff --git a/app/src/main/java/to/bitkit/ui/ContentView.kt b/app/src/main/java/to/bitkit/ui/ContentView.kt index 80183de21..b6cc35039 100644 --- a/app/src/main/java/to/bitkit/ui/ContentView.kt +++ b/app/src/main/java/to/bitkit/ui/ContentView.kt @@ -1,5 +1,9 @@ package to.bitkit.ui +import androidx.compose.animation.AnimatedContentScope +import androidx.compose.animation.AnimatedContentTransitionScope +import androidx.compose.animation.EnterTransition +import androidx.compose.animation.ExitTransition import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.DisposableEffect @@ -16,9 +20,12 @@ import androidx.lifecycle.Lifecycle import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.collectAsStateWithLifecycle +import androidx.navigation.NavBackStackEntry import androidx.navigation.NavController +import androidx.navigation.NavDeepLink import androidx.navigation.NavGraphBuilder import androidx.navigation.NavHostController +import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.navigation @@ -84,6 +91,7 @@ import to.bitkit.viewmodels.ExternalNodeViewModel import to.bitkit.viewmodels.MainScreenEffect import to.bitkit.viewmodels.TransferViewModel import to.bitkit.viewmodels.WalletViewModel +import kotlin.reflect.KType @Composable fun ContentView( @@ -439,12 +447,7 @@ private fun NavGraphBuilder.settings( viewModel: WalletViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { SettingsScreen(viewModel, navController) } } @@ -462,12 +465,7 @@ private fun NavGraphBuilder.nodeState( } private fun NavGraphBuilder.generalSettings(navController: NavHostController) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { GeneralSettingsScreen(navController) } } @@ -476,12 +474,7 @@ private fun NavGraphBuilder.defaultUnitSettings( currencyViewModel: CurrencyViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { DefaultUnitSettingsScreen(currencyViewModel, navController) } } @@ -490,12 +483,7 @@ private fun NavGraphBuilder.localCurrencySettings( currencyViewModel: CurrencyViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { LocalCurrencySettingsScreen(currencyViewModel, navController) } } @@ -503,12 +491,7 @@ private fun NavGraphBuilder.localCurrencySettings( private fun NavGraphBuilder.backupSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { BackupSettingsScreen(navController) } } @@ -516,12 +499,7 @@ private fun NavGraphBuilder.backupSettings( private fun NavGraphBuilder.backupWalletSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { BackupWalletScreen(navController) } } @@ -529,12 +507,7 @@ private fun NavGraphBuilder.backupWalletSettings( private fun NavGraphBuilder.restoreWalletSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { RestoreWalletScreen(navController) } } @@ -542,12 +515,7 @@ private fun NavGraphBuilder.restoreWalletSettings( private fun NavGraphBuilder.channelOrdersSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { ChannelOrdersScreen( onBackClick = { navController.popBackStack() }, onOrderItemClick = { navController.navigateToOrderDetail(it) }, @@ -559,12 +527,7 @@ private fun NavGraphBuilder.channelOrdersSettings( private fun NavGraphBuilder.orderDetailSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { navBackEntry -> + composableWithDefaultTransitions { navBackEntry -> OrderDetailScreen( orderItem = navBackEntry.toRoute(), onBackClick = { navController.popBackStack() }, @@ -575,12 +538,7 @@ private fun NavGraphBuilder.orderDetailSettings( private fun NavGraphBuilder.cjitDetailSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { navBackEntry -> + composableWithDefaultTransitions { navBackEntry -> CJitDetailScreen( cjitItem = navBackEntry.toRoute(), onBackClick = { navController.popBackStack() }, @@ -592,12 +550,7 @@ private fun NavGraphBuilder.lightning( viewModel: WalletViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { LightningSettingsScreen(viewModel, navController) } } @@ -606,12 +559,7 @@ private fun NavGraphBuilder.devSettings( viewModel: WalletViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { DevSettingsScreen(viewModel, navController) } } @@ -619,12 +567,7 @@ private fun NavGraphBuilder.devSettings( private fun NavGraphBuilder.regtestSettings( navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { val viewModel = hiltViewModel() BlocktankRegtestScreen(viewModel, navController) } @@ -634,12 +577,7 @@ private fun NavGraphBuilder.allActivity( viewModel: ActivityListViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { + composableWithDefaultTransitions { AllActivityScreen( viewModel = viewModel, onBackCLick = { navController.popBackStack() }, @@ -652,12 +590,7 @@ private fun NavGraphBuilder.activityItem( viewModel: ActivityListViewModel, navController: NavHostController, ) { - composable( - enterTransition = { screenSlideIn }, - exitTransition = { screenScaleOut }, - popEnterTransition = { screenScaleIn }, - popExitTransition = { screenSlideOut }, - ) { navBackEntry -> + composableWithDefaultTransitions { navBackEntry -> ActivityItemScreen( viewModel = viewModel, activityItem = navBackEntry.toRoute(), @@ -685,6 +618,29 @@ private fun NavGraphBuilder.qrScanner( } // endregion +/** + * Adds the [Composable] to the [NavGraphBuilder] with the default screen transitions. + */ +inline fun NavGraphBuilder.composableWithDefaultTransitions( + typeMap: Map> = emptyMap(), + deepLinks: List = emptyList(), + noinline enterTransition: (AnimatedContentTransitionScope.() -> EnterTransition?)? = { screenSlideIn }, + noinline exitTransition: (AnimatedContentTransitionScope.() -> ExitTransition?)? = { screenScaleOut }, + noinline popEnterTransition: (AnimatedContentTransitionScope.() -> EnterTransition?)? = { screenScaleIn }, + noinline popExitTransition: (AnimatedContentTransitionScope.() -> ExitTransition?)? = { screenSlideOut }, + noinline content: @Composable AnimatedContentScope.(NavBackStackEntry) -> Unit, +) { + composable( + typeMap = typeMap, + deepLinks = deepLinks, + enterTransition = enterTransition, + exitTransition = exitTransition, + popEnterTransition = popEnterTransition, + popExitTransition = popExitTransition, + content = content, + ) +} + // region events fun NavController.navigateToHome() = navigate( route = Routes.Home, diff --git a/app/src/main/java/to/bitkit/ui/screens/transfer/components/TransferAnimationView.kt b/app/src/main/java/to/bitkit/ui/screens/transfer/components/TransferAnimationView.kt index 7447371e9..b876d2176 100644 --- a/app/src/main/java/to/bitkit/ui/screens/transfer/components/TransferAnimationView.kt +++ b/app/src/main/java/to/bitkit/ui/screens/transfer/components/TransferAnimationView.kt @@ -2,6 +2,7 @@ package to.bitkit.ui.screens.transfer.components import androidx.annotation.DrawableRes import androidx.compose.animation.core.EaseInOut +import androidx.compose.animation.core.InfiniteRepeatableSpec import androidx.compose.animation.core.RepeatMode import androidx.compose.animation.core.animateFloat import androidx.compose.animation.core.infiniteRepeatable @@ -28,51 +29,46 @@ fun TransferAnimationView( @DrawableRes largeCircleRes: Int, @DrawableRes smallCircleRes: Int, @DrawableRes contentRes: Int = R.drawable.transfer, - rotateContent: Boolean = true + rotateContent: Boolean = true, ) { + val animationSpec: InfiniteRepeatableSpec = infiniteRepeatable( + animation = tween(durationMillis = 3000, easing = EaseInOut), + repeatMode = RepeatMode.Reverse, + ) + Box( contentAlignment = Alignment.Center, - modifier = Modifier.padding(horizontal = 16.dp) + modifier = Modifier.padding(horizontal = 16.dp), ) { val infiniteTransition = rememberInfiniteTransition("transition") + val rotationLarge by infiniteTransition.animateFloat( initialValue = 0f, - targetValue = -180f, - animationSpec = infiniteRepeatable( - animation = tween(durationMillis = 3000, easing = EaseInOut), - repeatMode = RepeatMode.Reverse, - ), - label = "rotationLarge" + targetValue = -90f, + animationSpec = animationSpec, + label = "rotationLarge", ) val rotationSmall by infiniteTransition.animateFloat( initialValue = 0f, - targetValue = 120f, - animationSpec = infiniteRepeatable( - animation = tween(durationMillis = 3000, easing = EaseInOut), - repeatMode = RepeatMode.Reverse, - ), - label = "rotationSmall" + targetValue = 60f, + animationSpec = animationSpec, + label = "rotationSmall", ) val rotationArrows by infiniteTransition.animateFloat( initialValue = 0f, targetValue = 70f, - animationSpec = infiniteRepeatable( - animation = tween(durationMillis = 3000, easing = EaseInOut), - repeatMode = RepeatMode.Reverse, - ), - label = "rotationArrows" + animationSpec = animationSpec, + label = "rotationArrows", ) Image( painter = painterResource(largeCircleRes), contentDescription = null, - modifier = Modifier - .rotate(rotationLarge) + modifier = Modifier.rotate(rotationLarge), ) Image( painter = painterResource(smallCircleRes), contentDescription = null, - modifier = Modifier - .rotate(rotationSmall) + modifier = Modifier.rotate(rotationSmall), ) Image( painter = painterResource(contentRes), @@ -80,22 +76,39 @@ fun TransferAnimationView( contentScale = ContentScale.Fit, modifier = Modifier .fillMaxWidth() - .apply { + .then( if (rotateContent) { - rotate(rotationArrows) - } - } + Modifier.rotate(rotationArrows) + } else { + Modifier + }, + ), + ) + } +} + +@Preview +@Composable +private fun PreviewSyncing() { + AppThemeSurface { + TransferAnimationView( + largeCircleRes = R.drawable.ln_sync_large, + smallCircleRes = R.drawable.ln_sync_small, + contentRes = R.drawable.transfer, + rotateContent = true, ) } } @Preview @Composable -private fun Preview() { +private fun PreviewNoContentRotation() { AppThemeSurface { TransferAnimationView( largeCircleRes = R.drawable.ln_sync_large, smallCircleRes = R.drawable.ln_sync_small, + contentRes = R.drawable.transfer, + rotateContent = false, ) } } diff --git a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt index be36220a8..66f2dba89 100644 --- a/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt +++ b/app/src/main/java/to/bitkit/ui/screens/wallets/send/SendAmountScreen.kt @@ -39,7 +39,6 @@ import to.bitkit.viewmodels.SendEvent import to.bitkit.viewmodels.SendMethod import to.bitkit.viewmodels.SendUiState - @Composable fun SendAmountScreen( uiState: SendUiState, @@ -67,7 +66,6 @@ fun SendAmountScreen( BalanceHeaderView(sats = uiState.amountInput.toLongOrDefault(0), modifier = Modifier.fillMaxWidth()) Spacer(modifier = Modifier.height(24.dp)) - Spacer(modifier = Modifier.weight(1f)) Text13Up( diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index 477759a34..bc7a4a50d 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -1,6 +1,6 @@ - -