diff --git a/app/src/androidTest/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreenTest.kt b/app/src/androidTest/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreenTest.kt index 10da997..39feecb 100644 --- a/app/src/androidTest/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreenTest.kt +++ b/app/src/androidTest/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreenTest.kt @@ -25,6 +25,7 @@ class LobbyScreenTest { LobbyScreen( state = LobbyUiState.Success(previewLobbyData()), onNavigate = {}, + onOpenWallet = {}, onRetry = {}, onUseCache = {}, ) @@ -49,6 +50,7 @@ class LobbyScreenTest { LobbyScreen( state = LobbyUiState.Success(previewLobbyData()), onNavigate = { navigated = it }, + onOpenWallet = {}, onRetry = {}, onUseCache = {}, ) @@ -76,6 +78,7 @@ class LobbyScreenTest { lastSyncedLabel = "Last synced 4 minutes ago", ), onNavigate = {}, + onOpenWallet = {}, onRetry = { retried = true }, onUseCache = { usedCache = true }, ) diff --git a/app/src/main/java/com/plainstudio/stackcasino/StackApp.kt b/app/src/main/java/com/plainstudio/stackcasino/StackApp.kt index 9367e35..eaa8028 100644 --- a/app/src/main/java/com/plainstudio/stackcasino/StackApp.kt +++ b/app/src/main/java/com/plainstudio/stackcasino/StackApp.kt @@ -41,7 +41,10 @@ fun StackApp(startDestination: StartDestination) { StackBottomBar( currentRoute = currentRoute, onTabSelected = { tab -> - navController.navigate(tab.route.path) { + // defaultPath instead of path so parametric tabs + // (Wallet) navigate to the bare destination + // without dragging the {tab} placeholder along. + navController.navigate(tab.route.defaultPath) { popUpTo(Route.Lobby.path) { saveState = true } launchSingleTop = true restoreState = true diff --git a/app/src/main/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreen.kt b/app/src/main/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreen.kt index ac4f647..62a4c9f 100644 --- a/app/src/main/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreen.kt +++ b/app/src/main/java/com/plainstudio/stackcasino/feature/lobby/LobbyScreen.kt @@ -84,6 +84,7 @@ import com.plainstudio.stackcasino.ui.theme.TextMedium fun LobbyScreen( state: LobbyUiState, onNavigate: (Route) -> Unit, + onOpenWallet: (initialTab: String?) -> Unit, onRetry: () -> Unit, onUseCache: () -> Unit, modifier: Modifier = Modifier, @@ -91,6 +92,7 @@ fun LobbyScreen( LobbyContent( state = state, onNavigate = onNavigate, + onOpenWallet = onOpenWallet, onRetry = onRetry, onUseCache = onUseCache, modifier = modifier, @@ -101,6 +103,7 @@ fun LobbyScreen( private fun LobbyContent( state: LobbyUiState, onNavigate: (Route) -> Unit, + onOpenWallet: (initialTab: String?) -> Unit, onRetry: () -> Unit, onUseCache: () -> Unit, modifier: Modifier = Modifier, @@ -112,6 +115,7 @@ private fun LobbyContent( SuccessContent( data = state.data, onNavigate = onNavigate, + onOpenWallet = onOpenWallet, ) LobbyUiState.Loading -> LoadingContent() is LobbyUiState.Error -> @@ -139,6 +143,7 @@ private fun LobbyContent( private fun SuccessContent( data: LobbyData, onNavigate: (Route) -> Unit, + onOpenWallet: (initialTab: String?) -> Unit, ) { var isBalanceHidden by rememberSaveable { mutableStateOf(false) } Column( @@ -161,7 +166,10 @@ private fun SuccessContent( onSelectGame = { onNavigate(it.toRoute()) }, ) Divider() - QuickActionsSection(onOpenWallet = { onNavigate(Route.Wallet) }) + QuickActionsSection( + onOpenDeposit = { onOpenWallet(QUICK_ACTION_TAB_DEPOSIT) }, + onOpenWithdraw = { onOpenWallet(QUICK_ACTION_TAB_WITHDRAW) }, + ) Divider() RecentActivitySection( rounds = data.recentActivity, @@ -584,7 +592,10 @@ private fun CoinflipCard( // --------------------------------------------------------------------------- @Composable -private fun QuickActionsSection(onOpenWallet: () -> Unit) { +private fun QuickActionsSection( + onOpenDeposit: () -> Unit, + onOpenWithdraw: () -> Unit, +) { Column( modifier = Modifier @@ -607,7 +618,7 @@ private fun QuickActionsSection(onOpenWallet: () -> Unit) { subtitle = "Receive crypto", accent = SemanticOk, isDeposit = true, - onClick = onOpenWallet, + onClick = onOpenDeposit, modifier = Modifier.weight(1f), ) QuickActionCard( @@ -615,13 +626,18 @@ private fun QuickActionsSection(onOpenWallet: () -> Unit) { subtitle = "Send to address", accent = SemanticWarn, isDeposit = false, - onClick = onOpenWallet, + onClick = onOpenWithdraw, modifier = Modifier.weight(1f), ) } } } +// Tab keys the lobby passes back to the nav-host so wallet deep-links +// land on the right pane. Match [WalletTab.name.lowercase()]. +internal const val QUICK_ACTION_TAB_DEPOSIT = "Deposit" +internal const val QUICK_ACTION_TAB_WITHDRAW = "Withdraw" + @Composable private fun QuickActionCard( title: String, @@ -1050,6 +1066,7 @@ private fun LobbyScreenSuccessPreview() { LobbyScreen( state = LobbyUiState.Success(previewLobbyData()), onNavigate = {}, + onOpenWallet = {}, onRetry = {}, onUseCache = {}, ) @@ -1063,6 +1080,7 @@ private fun LobbyScreenLoadingPreview() { LobbyScreen( state = LobbyUiState.Loading, onNavigate = {}, + onOpenWallet = {}, onRetry = {}, onUseCache = {}, ) @@ -1080,6 +1098,7 @@ private fun LobbyScreenErrorPreview() { lastSyncedLabel = "Last synced 4 minutes ago", ), onNavigate = {}, + onOpenWallet = {}, onRetry = {}, onUseCache = {}, ) diff --git a/app/src/main/java/com/plainstudio/stackcasino/feature/wallet/WalletScreen.kt b/app/src/main/java/com/plainstudio/stackcasino/feature/wallet/WalletScreen.kt index edd3d48..6ff4195 100644 --- a/app/src/main/java/com/plainstudio/stackcasino/feature/wallet/WalletScreen.kt +++ b/app/src/main/java/com/plainstudio/stackcasino/feature/wallet/WalletScreen.kt @@ -59,8 +59,9 @@ fun WalletScreen( data: WalletData, onNavigate: (Route) -> Unit, modifier: Modifier = Modifier, + initialTab: WalletTab = WalletTab.Deposit, ) { - var selectedTab by rememberSaveable { mutableStateOf(WalletTab.Deposit) } + var selectedTab by rememberSaveable { mutableStateOf(initialTab) } Surface(modifier = modifier.fillMaxSize(), color = SurfaceBase) { Column( modifier = diff --git a/app/src/main/java/com/plainstudio/stackcasino/navigation/Route.kt b/app/src/main/java/com/plainstudio/stackcasino/navigation/Route.kt index 4f5c2d2..2a5ebb4 100644 --- a/app/src/main/java/com/plainstudio/stackcasino/navigation/Route.kt +++ b/app/src/main/java/com/plainstudio/stackcasino/navigation/Route.kt @@ -15,12 +15,32 @@ package com.plainstudio.stackcasino.navigation */ sealed class Route( val path: String, + // Used by call sites that just want to "go to this destination" + // without supplying an argument. Defaults to [path] so static + // routes stay one-liners; parametric routes whose pattern carries + // optional query args (e.g. wallet?tab={tab}) override it to the + // bare path that produces the default landing state. + val defaultPath: String = path, ) { data object Login : Route("login") data object Lobby : Route("lobby") - data object Wallet : Route("wallet") + /** + * Wallet has three top-level tabs (Deposit / Withdraw / Transactions) + * and the lobby's quick actions deep-link to one of the first two. + * The optional `tab` query arg surfaces that choice without spinning + * up a second route; navigating to `"wallet"` lands on the default + * Deposit tab. + */ + data object Wallet : Route( + path = "wallet?tab={tab}", + defaultPath = "wallet", + ) { + const val ARG_TAB = "tab" + + fun build(tab: String? = null): String = if (tab.isNullOrBlank()) defaultPath else "wallet?tab=$tab" + } data object HouseWallet : Route("house_wallet") diff --git a/app/src/main/java/com/plainstudio/stackcasino/navigation/StackNavHost.kt b/app/src/main/java/com/plainstudio/stackcasino/navigation/StackNavHost.kt index 431ae59..62176b4 100644 --- a/app/src/main/java/com/plainstudio/stackcasino/navigation/StackNavHost.kt +++ b/app/src/main/java/com/plainstudio/stackcasino/navigation/StackNavHost.kt @@ -23,6 +23,7 @@ import com.plainstudio.stackcasino.feature.lobby.previewLobbyData import com.plainstudio.stackcasino.feature.news.NewsDetailScreen import com.plainstudio.stackcasino.feature.news.NewsScreen import com.plainstudio.stackcasino.feature.wallet.WalletScreen +import com.plainstudio.stackcasino.feature.wallet.WalletTab import com.plainstudio.stackcasino.feature.wallet.previewWalletData /** @@ -63,20 +64,16 @@ fun StackNavHost( LobbyScreen( state = LobbyUiState.Success(previewLobbyData()), onNavigate = { route -> - navController.navigate(route.path) { launchSingleTop = true } + navController.navigate(route.defaultPath) { launchSingleTop = true } + }, + onOpenWallet = { tab -> + navController.navigate(Route.Wallet.build(tab)) { launchSingleTop = true } }, onRetry = {}, onUseCache = {}, ) } - composable(Route.Wallet.path) { - WalletScreen( - data = previewWalletData(), - onNavigate = { route -> - navController.navigate(route.path) { launchSingleTop = true } - }, - ) - } + addWalletRoute(navController) composable(Route.History.path) { HistoryScreen( data = historyPreviewData(), @@ -106,6 +103,38 @@ fun StackNavHost( } } +/** + * Wallet has an optional `tab` query arg so the lobby quick actions + * can deep-link to Deposit / Withdraw; navigating to plain "wallet" + * lands on the default Deposit tab. Pulled out of [StackNavHost] so + * the entry function stays under the detekt LongMethod budget. + */ +private fun NavGraphBuilder.addWalletRoute(navController: NavHostController) { + composable( + route = Route.Wallet.path, + arguments = + listOf( + navArgument(Route.Wallet.ARG_TAB) { + type = NavType.StringType + nullable = true + defaultValue = null + }, + ), + ) { entry -> + val tabName = entry.arguments?.getString(Route.Wallet.ARG_TAB) + val initialTab = + tabName?.let { runCatching { WalletTab.valueOf(it) }.getOrNull() } + ?: WalletTab.Deposit + WalletScreen( + data = previewWalletData(), + initialTab = initialTab, + onNavigate = { route -> + navController.navigate(route.defaultPath) { launchSingleTop = true } + }, + ) + } +} + /** * Routes with placeholders for their string argument. Kept out of the * main [StackNavHost] body so the entry function stays under the