1 /*
<lambda>null2  * Copyright (C) 2023 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 
17 package com.android.permissioncontroller.role.ui.wear
18 
19 import android.content.pm.ApplicationInfo
20 import android.util.Pair
21 import androidx.compose.foundation.layout.Spacer
22 import androidx.compose.foundation.layout.height
23 import androidx.compose.runtime.Composable
24 import androidx.compose.runtime.getValue
25 import androidx.compose.runtime.livedata.observeAsState
26 import androidx.compose.runtime.mutableStateOf
27 import androidx.compose.runtime.remember
28 import androidx.compose.runtime.setValue
29 import androidx.compose.ui.Modifier
30 import androidx.compose.ui.platform.testTag
31 import androidx.compose.ui.res.stringResource
32 import androidx.compose.ui.unit.dp
33 import androidx.wear.compose.material.ChipDefaults
34 import androidx.wear.compose.material.MaterialTheme
35 import com.android.permissioncontroller.R
36 import com.android.permissioncontroller.permission.ui.wear.elements.Chip
37 import com.android.permissioncontroller.permission.ui.wear.elements.ListFooter
38 import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
39 import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
40 import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
41 import com.android.permissioncontroller.permission.ui.wear.elements.toggleChipBackgroundColors
42 import com.android.permissioncontroller.role.ui.ManageRoleHolderStateLiveData
43 
44 @Composable
45 fun WearRequestRoleScreen(
46     helper: WearRequestRoleHelper,
47     onSetAsDefault: (Boolean, String?) -> Unit,
48     onCanceled: () -> Unit
49 ) {
50     val roleLiveData = helper.viewModel.roleLiveData.observeAsState(emptyList())
51     val manageRoleHolderState =
52         helper.viewModel.manageRoleHolderStateLiveData.observeAsState(
53             ManageRoleHolderStateLiveData.STATE_WORKING
54         )
55     val dontAskAgain = helper.wearViewModel.dontAskAgain.observeAsState(false)
56     val selectedPackageName = helper.wearViewModel.selectedPackageName.observeAsState(null)
57     var isLoading by remember { mutableStateOf(true) }
58 
59     if (isLoading && roleLiveData.value.isNotEmpty()) {
60         helper.initializeHolderPackageName(roleLiveData.value)
61         helper.initializeSelectedPackageName()
62     }
63 
64     val onCheckedChanged: (Boolean, String?, Boolean) -> Unit = { checked, packageName, isHolder ->
65         if (checked) {
66             helper.wearViewModel.selectedPackageName.value = packageName
67             helper.wearViewModel.isHolderChecked = isHolder
68         }
69     }
70 
71     val onDontAskAgainCheckedChanged: (Boolean) -> Unit = { checked ->
72         helper.wearViewModel.dontAskAgain.value = checked
73         if (checked) {
74             helper.initializeSelectedPackageName()
75         }
76     }
77 
78     WearRequestRoleContent(
79         isLoading,
80         helper,
81         roleLiveData.value,
82         manageRoleHolderState.value == ManageRoleHolderStateLiveData.STATE_IDLE,
83         dontAskAgain.value,
84         selectedPackageName.value,
85         onCheckedChanged,
86         onDontAskAgainCheckedChanged,
87         onSetAsDefault,
88         onCanceled
89     )
90 
91     if (isLoading && roleLiveData.value.isNotEmpty()) {
92         isLoading = false
93     }
94 }
95 
96 @Composable
WearRequestRoleContentnull97 internal fun WearRequestRoleContent(
98     isLoading: Boolean,
99     helper: WearRequestRoleHelper,
100     qualifyingApplications: List<Pair<ApplicationInfo, Boolean>>,
101     enabled: Boolean,
102     dontAskAgain: Boolean,
103     selectedPackageName: String?,
104     onCheckedChanged: (Boolean, String?, Boolean) -> Unit,
105     onDontAskAgainCheckedChanged: (Boolean) -> Unit,
106     onSetAsDefault: (Boolean, String?) -> Unit,
107     onCanceled: () -> Unit
108 ) {
109     ScrollableScreen(
110         image = helper.getIcon(),
111         title = helper.getTitle(),
112         showTimeText = false,
113         isLoading = isLoading
114     ) {
115         helper.getNonePreference(qualifyingApplications, selectedPackageName)?.let {
116             item {
117                 ToggleChip(
118                     label = it.label,
119                     icon = it.icon,
120                     enabled = enabled && it.enabled,
121                     checked = it.checked,
122                     onCheckedChanged = { checked ->
123                         run { onCheckedChanged(checked, it.packageName, it.isHolder) }
124                     },
125                     toggleControl = ToggleChipToggleControl.Radio,
126                     labelMaxLine = Integer.MAX_VALUE
127                 )
128             }
129             it.subTitle?.let { subTitle -> item { ListFooter(description = subTitle) } }
130         }
131 
132         for (pref in helper.getPreferences(qualifyingApplications, selectedPackageName)) {
133             item {
134                 ToggleChip(
135                     label = pref.label,
136                     icon = pref.icon,
137                     enabled = enabled && pref.enabled,
138                     checked = pref.checked,
139                     onCheckedChanged = { checked ->
140                         run { onCheckedChanged(checked, pref.packageName, pref.isHolder) }
141                     },
142                     toggleControl = ToggleChipToggleControl.Radio,
143                 )
144             }
145             pref.subTitle?.let { subTitle -> item { ListFooter(description = subTitle) } }
146         }
147 
148         if (helper.showDontAskButton()) {
149             item {
150                 ToggleChip(
151                     checked = dontAskAgain,
152                     enabled = enabled,
153                     onCheckedChanged = { checked -> run { onDontAskAgainCheckedChanged(checked) } },
154                     label = stringResource(R.string.request_role_dont_ask_again),
155                     toggleControl = ToggleChipToggleControl.Checkbox,
156                     colors = toggleChipBackgroundColors(),
157                     modifier =
158                         Modifier.testTag("com.android.permissioncontroller:id/dont_ask_again"),
159                 )
160             }
161         }
162 
163         item { Spacer(modifier = Modifier.height(14.dp)) }
164 
165         item {
166             Chip(
167                 label = stringResource(R.string.request_role_set_as_default),
168                 textColor = MaterialTheme.colors.background,
169                 colors = ChipDefaults.primaryChipColors(),
170                 enabled = helper.shouldSetAsDefaultEnabled(enabled),
171                 onClick = { onSetAsDefault(dontAskAgain, selectedPackageName) },
172                 modifier = Modifier.testTag("android:id/button1"),
173             )
174         }
175         item {
176             Chip(
177                 label = stringResource(R.string.cancel),
178                 enabled = enabled,
179                 onClick = { onCanceled() },
180                 modifier = Modifier.testTag("android:id/button2"),
181             )
182         }
183     }
184 }
185