From 95f5e4aba609fc953b0d78099a63332ecdef47cd Mon Sep 17 00:00:00 2001 From: Simone Mapelli Date: Tue, 30 Dec 2025 12:21:23 +0100 Subject: [PATCH 1/2] Add bottom ad banner to navigation screens --- .../core/presentation/navigation/NavGraph.kt | 128 ++++++++++++------ .../mathbrainer/navigation/NavGraph.kt | 46 +++++-- 2 files changed, 123 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt b/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt index 693425a..dbf411f 100644 --- a/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt +++ b/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt @@ -1,6 +1,9 @@ package eu.indiewalkabout.mathbrainer.core.presentation.navigation import android.util.Log +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.hilt.navigation.compose.hiltViewModel @@ -9,6 +12,10 @@ import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import eu.indiewalkabout.mathbrainer.R +import eu.indiewalkabout.mathbrainer.feat_ads.presentation.AdMobBannerView import eu.indiewalkabout.mathbrainer.feat_credits.presentation.ui.GameCreditsScreen import eu.indiewalkabout.mathbrainer.feat_games.feat_count_items.presentation.ui.CountObjectsGameScreen import eu.indiewalkabout.mathbrainer.feat_games.feat_enigma.presentation.ui.EnigmaGameScreen @@ -47,10 +54,12 @@ fun NavGraph( // --- Home --- composable(ScreenRoutes.Home.route) { val viewModel = hiltViewModel() - HomeScreen( - navController = navController, - homeViewModel = viewModel - ) + ScreenWithBottomBanner { + HomeScreen( + navController = navController, + homeViewModel = viewModel + ) + } } // --- MathWrite Game --- @@ -63,10 +72,12 @@ fun NavGraph( val encodedOperation = backStackEntry.arguments?.getString("operation") ?: "+" val operation = URLDecoder.decode(encodedOperation, "UTF-8") - MathWriteGameScreen( - operation = operation, - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + MathWriteGameScreen( + operation = operation, + onBack = { navController.popBackStack() } + ) + } } // --- MathChoose Game --- @@ -79,83 +90,120 @@ fun NavGraph( val encodedOperation = backStackEntry.arguments?.getString("operation") ?: "+" val operation = java.net.URLDecoder.decode(encodedOperation, "UTF-8") - MathChooseGameScreen( - operation = operation, - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + MathChooseGameScreen( + operation = operation, + onBack = { navController.popBackStack() } + ) + } } // --- Double Number Game --- composable(route = ScreenRoutes.DoubleNumberGame.route) { - DoubleNumberGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + DoubleNumberGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Random Operation Game --- composable(route = ScreenRoutes.RandomOperationGame.route) { - RandomOperationGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + RandomOperationGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Memory Flash Game --- composable(route = ScreenRoutes.MemoryFlashGame.route) { - MemoryFlashGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + MemoryFlashGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Number Order Game --- composable(route = ScreenRoutes.NumberOrderGame.route) { - NumberOrderGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + NumberOrderGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Count Objects Game --- composable(route = ScreenRoutes.CountObjectsGame.route) { - CountObjectsGameScreen(onBack = { navController.popBackStack() }) + ScreenWithBottomBanner { + CountObjectsGameScreen(onBack = { navController.popBackStack() }) + } } // --- Sequence Completion Game --- composable(route = ScreenRoutes.SequenceCompleteGame.route) { - SequenceCompleteGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + SequenceCompleteGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Falling Operations Game --- composable(route = ScreenRoutes.FallingOpsGame.route) { - FallingOpsGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + FallingOpsGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Enigma Game --- composable(route = ScreenRoutes.EnigmaGame.route) { - EnigmaGameScreen( - onBack = { navController.popBackStack() } - ) + ScreenWithBottomBanner { + EnigmaGameScreen( + onBack = { navController.popBackStack() } + ) + } } // --- Settings --- composable(ScreenRoutes.GameSettings.route) { - GameSettingsScreen( - onBack = { navController.popBackStack() }, - onCreditsClick = { navController.navigate(ScreenRoutes.GameCredits.route) } - ) + ScreenWithBottomBanner { + GameSettingsScreen( + onBack = { navController.popBackStack() }, + onCreditsClick = { navController.navigate(ScreenRoutes.GameCredits.route) } + ) + } } // --- Credits --- composable(ScreenRoutes.GameCredits.route) { - GameCreditsScreen(onBack = { navController.popBackStack() }) + ScreenWithBottomBanner { + GameCreditsScreen(onBack = { navController.popBackStack() }) + } } // --- Statistics --- composable(ScreenRoutes.Statistics.route) { val viewModel = hiltViewModel() - StatisticScreen(navController = navController, statisticViewModel = viewModel) + ScreenWithBottomBanner { + StatisticScreen(navController = navController, statisticViewModel = viewModel) + } + } + } +} + +@Composable +private fun ScreenWithBottomBanner(content: @Composable () -> Unit) { + Column(modifier = Modifier.fillMaxSize()) { + Box(modifier = Modifier.weight(1f, fill = true)) { + content() } + AdMobBannerView( + adUnitId = stringResource(R.string.admob_key_bottom_banner), + modifier = Modifier.fillMaxWidth() + ) } } diff --git a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt b/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt index 4cc9308..1c314f4 100644 --- a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt +++ b/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt @@ -1,6 +1,9 @@ package eu.indiewalkabout.mathbrainer.navigation import android.util.Log +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.hilt.navigation.compose.hiltViewModel @@ -9,6 +12,10 @@ import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource +import eu.indiewalkabout.mathbrainer.R +import eu.indiewalkabout.mathbrainer.feat_ads.presentation.AdMobBannerView import eu.indiewalkabout.mathbrainer.feat_games.feat_math_op_write.presentation.ui.MathWriteGameScreen import eu.indiewalkabout.mathbrainer.feat_home.presentation.ui.HomeScreen import eu.indiewalkabout.mathbrainer.feat_home.presentation.ui.HomeViewModel @@ -31,12 +38,14 @@ fun NavGraph( ) { composable(ScreenRoutes.Home.route) { val viewModel = hiltViewModel() - HomeScreen( - navController = navController, - homeViewModel = viewModel - ) + ScreenWithBottomBanner { + HomeScreen( + navController = navController, + homeViewModel = viewModel + ) + } } - + composable( route = ScreenRoutes.MathWriteGame.route, arguments = listOf( @@ -47,12 +56,27 @@ fun NavGraph( val encodedOperation = backStackEntry.arguments?.getString("operation") ?: "+" val operation = java.net.URLDecoder.decode(encodedOperation, "UTF-8") val highScore = backStackEntry.arguments?.getInt("highScore") ?: 0 - - MathWriteGameScreen( - operation = operation, - initialHighScore = highScore, - onBack = { navController.popBackStack() } - ) + + ScreenWithBottomBanner { + MathWriteGameScreen( + operation = operation, + initialHighScore = highScore, + onBack = { navController.popBackStack() } + ) + } + } + } +} + +@Composable +private fun ScreenWithBottomBanner(content: @Composable () -> Unit) { + Column(modifier = Modifier.fillMaxSize()) { + Box(modifier = Modifier.weight(1f, fill = true)) { + content() } + AdMobBannerView( + adUnitId = stringResource(R.string.admob_key_bottom_banner), + modifier = Modifier.fillMaxWidth() + ) } } From 91e44a1604e51e3eb7b8824dccdcda8ab87df4c7 Mon Sep 17 00:00:00 2001 From: simone Date: Tue, 30 Dec 2025 12:40:29 +0100 Subject: [PATCH 2/2] feat: admob banner shown in each screen --- .../core/presentation/navigation/NavGraph.kt | 5 +- .../mathbrainer/navigation/NavGraph.kt | 82 ------------------- .../mathbrainer/navigation/ScreenRoutes.kt | 13 --- 3 files changed, 3 insertions(+), 97 deletions(-) delete mode 100644 app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt delete mode 100644 app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/ScreenRoutes.kt diff --git a/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt b/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt index dbf411f..c0f7148 100644 --- a/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt +++ b/app/src/main/java/eu/indiewalkabout/mathbrainer/core/presentation/navigation/NavGraph.kt @@ -4,16 +4,17 @@ import android.util.Log import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.NavType import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.navArgument -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource import eu.indiewalkabout.mathbrainer.R import eu.indiewalkabout.mathbrainer.feat_ads.presentation.AdMobBannerView import eu.indiewalkabout.mathbrainer.feat_credits.presentation.ui.GameCreditsScreen diff --git a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt b/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt deleted file mode 100644 index 1c314f4..0000000 --- a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/NavGraph.kt +++ /dev/null @@ -1,82 +0,0 @@ -package eu.indiewalkabout.mathbrainer.navigation - -import android.util.Log -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.hilt.navigation.compose.hiltViewModel -import androidx.navigation.NavHostController -import androidx.navigation.NavType -import androidx.navigation.compose.NavHost -import androidx.navigation.compose.composable -import androidx.navigation.navArgument -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.stringResource -import eu.indiewalkabout.mathbrainer.R -import eu.indiewalkabout.mathbrainer.feat_ads.presentation.AdMobBannerView -import eu.indiewalkabout.mathbrainer.feat_games.feat_math_op_write.presentation.ui.MathWriteGameScreen -import eu.indiewalkabout.mathbrainer.feat_home.presentation.ui.HomeScreen -import eu.indiewalkabout.mathbrainer.feat_home.presentation.ui.HomeViewModel - -@Composable -fun NavGraph( - navController: NavHostController, - startDestination: String = ScreenRoutes.Home.route -) { - // Log navigation events - LaunchedEffect(navController) { - navController.addOnDestinationChangedListener { _, destination, _ -> - Log.d("Navigation", "Navigated to: ${destination.route}") - } - } - - NavHost( - navController = navController, - startDestination = startDestination - ) { - composable(ScreenRoutes.Home.route) { - val viewModel = hiltViewModel() - ScreenWithBottomBanner { - HomeScreen( - navController = navController, - homeViewModel = viewModel - ) - } - } - - composable( - route = ScreenRoutes.MathWriteGame.route, - arguments = listOf( - navArgument("operation") { type = NavType.StringType }, - navArgument("highScore") { type = NavType.IntType } - ) - ) { backStackEntry -> - val encodedOperation = backStackEntry.arguments?.getString("operation") ?: "+" - val operation = java.net.URLDecoder.decode(encodedOperation, "UTF-8") - val highScore = backStackEntry.arguments?.getInt("highScore") ?: 0 - - ScreenWithBottomBanner { - MathWriteGameScreen( - operation = operation, - initialHighScore = highScore, - onBack = { navController.popBackStack() } - ) - } - } - } -} - -@Composable -private fun ScreenWithBottomBanner(content: @Composable () -> Unit) { - Column(modifier = Modifier.fillMaxSize()) { - Box(modifier = Modifier.weight(1f, fill = true)) { - content() - } - AdMobBannerView( - adUnitId = stringResource(R.string.admob_key_bottom_banner), - modifier = Modifier.fillMaxWidth() - ) - } -} diff --git a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/ScreenRoutes.kt b/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/ScreenRoutes.kt deleted file mode 100644 index 3c9f096..0000000 --- a/app/src/main/java/eu/indiewalkabout/mathbrainer/navigation/ScreenRoutes.kt +++ /dev/null @@ -1,13 +0,0 @@ -package eu.indiewalkabout.mathbrainer.navigation - -import java.net.URLEncoder - -sealed class ScreenRoutes(val route: String) { - object Home : ScreenRoutes("home") - object MathWriteGame : ScreenRoutes("math_write_game/{operation}") { - fun createRoute(operation: String): String { - val encodedOperation = URLEncoder.encode(operation, "UTF-8") - return "math_write_game/$encodedOperation" - } - } -}