Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent the Map from requesting location more than once. #309

Merged
merged 2 commits into from
May 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}
}
Expand All @@ -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()
Expand Down Expand Up @@ -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(
Expand Down
35 changes: 1 addition & 34 deletions app/src/main/java/com/github/swent/echo/compose/map/Map.kt
Original file line number Diff line number Diff line change
@@ -1,28 +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.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
Expand All @@ -45,14 +37,6 @@ fun <T : View> 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.
*
Expand All @@ -69,25 +53,8 @@ fun MapDrawer(
callback: (Event) -> Unit = {},
launchEventCreation: (LatLng) -> Unit = {},
mapDrawerViewModel: MapDrawerViewModel = hiltViewModel(),
displayLocation: Boolean = false
) {
var displayLocation by remember { mutableStateOf(false) }
var permissionWasDenied = false
val launcher =
rememberLauncherForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { p
->
permissionWasDenied = !p.values.any { it }
displayLocation = displayLocation || !permissionWasDenied
}
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 (!permissionWasDenied && runBlocking { permissionsDenied(c) }) {
SideEffect { launcher.launch(PERMISSIONS) }
} else {
SideEffect { displayLocation = true }
}
EchoAndroidView(
modifier = modifier.testTag("mapViewWrapper"),
factory = mapDrawerViewModel::factory,
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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,
Expand All @@ -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) {
Expand Down