From 2c07ef27e9c490005dd1342e289f3dc8ee9ddd4a Mon Sep 17 00:00:00 2001 From: alejandrocalles Date: Fri, 17 May 2024 16:29:49 +0200 Subject: [PATCH] Move the permissions handler to the `AppNavigationHost`. --- .../echo/compose/components/HomeScreen.kt | 14 ++++-- .../com/github/swent/echo/compose/map/Map.kt | 35 +-------------- .../compose/navigation/AppNavigationHost.kt | 45 ++++++++++++++++++- 3 files changed, 55 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/com/github/swent/echo/compose/components/HomeScreen.kt b/app/src/main/java/com/github/swent/echo/compose/components/HomeScreen.kt index e563797dc..01fb7a26c 100644 --- a/app/src/main/java/com/github/swent/echo/compose/components/HomeScreen.kt +++ b/app/src/main/java/com/github/swent/echo/compose/components/HomeScreen.kt @@ -32,7 +32,11 @@ import kotlinx.serialization.json.Json * view, and the map. */ @Composable -fun HomeScreen(navActions: NavigationActions, homeScreenViewModel: HomeScreenViewModel) { +fun HomeScreen( + navActions: NavigationActions, + homeScreenViewModel: HomeScreenViewModel, + hasLocationPermissions: Boolean = false +) { // Drawer state to open and close the hamburger menu val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed) @@ -73,7 +77,7 @@ fun HomeScreen(navActions: NavigationActions, homeScreenViewModel: HomeScreenVie SearchButton(onClick = { homeScreenViewModel.setOverlay(Overlay.SEARCH_SHEET) }) } ) { paddingValues -> - Content(paddingValues, navActions, homeScreenViewModel) + Content(paddingValues, navActions, homeScreenViewModel, hasLocationPermissions) } } } @@ -82,7 +86,8 @@ fun HomeScreen(navActions: NavigationActions, homeScreenViewModel: HomeScreenVie private fun Content( paddingValues: PaddingValues, navActions: NavigationActions, - homeScreenViewModel: HomeScreenViewModel + homeScreenViewModel: HomeScreenViewModel, + hasLocationPermissions: Boolean = false ) { val mode by homeScreenViewModel.mode.collectAsState() @@ -130,7 +135,8 @@ private fun Content( launchEventCreation = { val encodedLocation = Json.encodeToString(Location("", it)) navActions.navigateTo(Routes.CREATE_EVENT.build(encodedLocation)) - } + }, + displayLocation = hasLocationPermissions ) if (!searchMode) { TagUI( diff --git a/app/src/main/java/com/github/swent/echo/compose/map/Map.kt b/app/src/main/java/com/github/swent/echo/compose/map/Map.kt index 191a557e3..82fe69a0d 100644 --- a/app/src/main/java/com/github/swent/echo/compose/map/Map.kt +++ b/app/src/main/java/com/github/swent/echo/compose/map/Map.kt @@ -1,29 +1,20 @@ package com.github.swent.echo.compose.map -import android.Manifest import android.content.Context -import android.content.pm.PackageManager import android.view.View -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable -import androidx.compose.runtime.SideEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier -import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.testTag import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel import com.github.swent.echo.data.model.Event import com.github.swent.echo.data.model.Location import com.github.swent.echo.viewmodels.MapDrawerViewModel import com.mapbox.mapboxsdk.geometry.LatLng -import kotlinx.coroutines.runBlocking val MAP_CENTER = Location("EPFL", 46.5191, 6.5668) const val DEFAULT_ZOOM = 13.0 @@ -46,14 +37,6 @@ fun EchoAndroidView( ) } -val PERMISSIONS = - arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) - -fun permissionsDenied(context: Context) = - PERMISSIONS.all { - ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_DENIED - } - /** * This composable will draw a map that displays events. * @@ -70,24 +53,8 @@ fun MapDrawer( callback: (Event) -> Unit = {}, launchEventCreation: (LatLng) -> Unit = {}, mapDrawerViewModel: MapDrawerViewModel = hiltViewModel(), + displayLocation: Boolean = false ) { - var displayLocation by remember { mutableStateOf(false) } - var alreadyDeniedPermissions by rememberSaveable { mutableStateOf(false) } - val launcher = - rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { p - -> - alreadyDeniedPermissions = !p.values.any { it } - } - val c = LocalContext.current - /* - This has to be blocking as we don't want the `EchoAndroidView` to be - created before launching the permission request. - */ - if (!alreadyDeniedPermissions && runBlocking { permissionsDenied(c) }) { - SideEffect { launcher.launch(PERMISSIONS) } - } else { - SideEffect { displayLocation = !alreadyDeniedPermissions } - } EchoAndroidView( modifier = modifier.testTag("mapViewWrapper"), factory = mapDrawerViewModel::factory, diff --git a/app/src/main/java/com/github/swent/echo/compose/navigation/AppNavigationHost.kt b/app/src/main/java/com/github/swent/echo/compose/navigation/AppNavigationHost.kt index bc858c651..98105f18b 100644 --- a/app/src/main/java/com/github/swent/echo/compose/navigation/AppNavigationHost.kt +++ b/app/src/main/java/com/github/swent/echo/compose/navigation/AppNavigationHost.kt @@ -1,11 +1,24 @@ package com.github.swent.echo.compose.navigation // import com.github.swent.echo.compose.authentication.ProfileCreationScreen +import android.Manifest import android.app.Activity +import android.content.Context +import android.content.pm.PackageManager import androidx.activity.compose.BackHandler +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.SideEffect +import androidx.compose.runtime.currentRecomposeScope +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext +import androidx.core.content.ContextCompat import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost @@ -24,6 +37,15 @@ import com.github.swent.echo.compose.myevents.MyEventsScreen import com.github.swent.echo.data.repository.Repository import com.github.swent.echo.ui.navigation.NavigationActions import com.github.swent.echo.ui.navigation.Routes +import kotlinx.coroutines.runBlocking + +val LOCATION_PERMISSIONS = + arrayOf(Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION) + +fun locationPermissionsDenied(context: Context) = + LOCATION_PERMISSIONS.all { + ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_DENIED + } /** * Navigation composable, it display the relevant screen based on the route and pass an instance of @@ -61,6 +83,16 @@ fun AppNavigationHost( navActions.navigateTo(Routes.MAP) } } + // Handle Permissions + var hasLocationPermissions by remember { mutableStateOf(false) } + var alreadyDeniedLocationPermissions by rememberSaveable { mutableStateOf(false) } + val scope = currentRecomposeScope + val launcher = + rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { p + -> + alreadyDeniedLocationPermissions = !p.values.any { it } + scope.invalidate() + } NavHost( navController = navController, @@ -83,7 +115,18 @@ fun AppNavigationHost( composable(Routes.MAP.name) { QuitAppOnHardwareBackButtonPressPress() - HomeScreen(homeScreenViewModel = hiltViewModel(), navActions = navActions) + // Run this if-else block on every Route that might need location permissions + val c = LocalContext.current + if (!alreadyDeniedLocationPermissions && runBlocking { locationPermissionsDenied(c) }) { + SideEffect { launcher.launch(LOCATION_PERMISSIONS) } + } else { + SideEffect { hasLocationPermissions = !alreadyDeniedLocationPermissions } + } + HomeScreen( + homeScreenViewModel = hiltViewModel(), + navActions = navActions, + hasLocationPermissions = hasLocationPermissions + ) } composable(Routes.CREATE_EVENT.name) {