1 /*
<lambda>null2 * Copyright (C) 2024 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package com.google.jetpackcamera.permissions
17
18 import android.Manifest
19 import android.util.Log
20 import androidx.activity.compose.rememberLauncherForActivityResult
21 import androidx.activity.result.contract.ActivityResultContracts
22 import androidx.compose.runtime.Composable
23 import androidx.compose.runtime.LaunchedEffect
24 import androidx.compose.runtime.collectAsState
25 import androidx.compose.runtime.getValue
26 import androidx.compose.ui.Modifier
27 import androidx.hilt.navigation.compose.hiltViewModel
28 import com.google.accompanist.permissions.ExperimentalPermissionsApi
29 import com.google.accompanist.permissions.MultiplePermissionsState
30 import com.google.accompanist.permissions.rememberMultiplePermissionsState
31 import com.google.accompanist.permissions.rememberPermissionState
32 import com.google.jetpackcamera.permissions.ui.PermissionTemplate
33
34 private const val TAG = "PermissionsScreen"
35
36 @OptIn(ExperimentalPermissionsApi::class)
37 @Composable
38 fun PermissionsScreen(
39 shouldRequestAudioPermission: Boolean,
40 onAllPermissionsGranted: () -> Unit,
41 openAppSettings: () -> Unit
42 ) {
43 val permissionStates = rememberMultiplePermissionsState(
44 permissions = if (shouldRequestAudioPermission) {
45 listOf(
46 Manifest.permission.CAMERA,
47 Manifest.permission.RECORD_AUDIO
48 )
49 } else {
50 listOf(
51 Manifest.permission.CAMERA
52 )
53 }
54 )
55 PermissionsScreen(
56 permissionStates = permissionStates,
57 onAllPermissionsGranted = onAllPermissionsGranted,
58 openAppSettings = openAppSettings
59 )
60 }
61
62 /**
63 * Permission prompts screen.
64 * Camera permission will always prompt when disabled, and the app cannot be used otherwise
65 * if optional settings have not yet been declined by the user, then they will be prompted as well
66 */
67 @OptIn(ExperimentalPermissionsApi::class)
68 @Composable
PermissionsScreennull69 fun PermissionsScreen(
70 modifier: Modifier = Modifier,
71 onAllPermissionsGranted: () -> Unit,
72 openAppSettings: () -> Unit,
73 permissionStates: MultiplePermissionsState,
74 viewModel: PermissionsViewModel = hiltViewModel<
75 PermissionsViewModel,
76 PermissionsViewModel.Factory
77 > { factory -> factory.create(permissionStates) }
78 ) {
79 Log.d(TAG, "PermissionsScreen")
80 val permissionsUiState: PermissionsUiState by viewModel.permissionsUiState.collectAsState()
<lambda>null81 LaunchedEffect(permissionsUiState) {
82 if (permissionsUiState is PermissionsUiState.AllPermissionsGranted) {
83 onAllPermissionsGranted()
84 }
85 }
86
87 if (permissionsUiState is PermissionsUiState.PermissionsNeeded) {
88 val permissionEnum =
89 (permissionsUiState as PermissionsUiState.PermissionsNeeded).currentPermission
90 val currentPermissionState =
91 rememberPermissionState(
92 permission = permissionEnum.getPermission()
93 )
94
95 val permissionLauncher = rememberLauncherForActivityResult(
96 contract = ActivityResultContracts.RequestPermission(),
permissionGrantednull97 onResult = { permissionGranted ->
98 if (permissionGranted) {
99 // remove from list
100 viewModel.dismissPermission()
101 } else if (permissionEnum.isOptional()) {
102 viewModel.dismissPermission()
103 }
104 }
105 )
106
107 PermissionTemplate(
108 modifier = modifier,
109 permissionEnum = permissionEnum,
110 permissionState = currentPermissionState,
111 onSkipPermission = when (permissionEnum) {
112 // todo: a prettier navigation to app settings.
113 PermissionEnum.CAMERA -> null
114 // todo: skip permission button functionality. currently need to go through the
115 // prompt to skip
116 else -> null // permissionsViewModel::dismissPermission
117 },
<lambda>null118 onRequestPermission = { permissionLauncher.launch(permissionEnum.getPermission()) },
119 onOpenAppSettings = openAppSettings
120 )
121 }
122 }
123