1 /*
2 * 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.permission.ui.wear
18
19 import androidx.compose.foundation.layout.Box
20 import androidx.compose.runtime.Composable
21 import androidx.compose.runtime.getValue
22 import androidx.compose.runtime.livedata.observeAsState
23 import androidx.compose.runtime.mutableStateOf
24 import androidx.compose.runtime.remember
25 import androidx.compose.runtime.setValue
26 import androidx.compose.ui.res.stringResource
27 import androidx.wear.compose.foundation.lazy.rememberScalingLazyListState
28 import com.android.permissioncontroller.R
29 import com.android.permissioncontroller.permission.ui.wear.elements.AlertDialog
30 import com.android.permissioncontroller.permission.ui.wear.elements.Chip
31 import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
32 import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChip
33 import com.android.permissioncontroller.permission.ui.wear.elements.ToggleChipToggleControl
34 import com.android.permissioncontroller.permission.ui.wear.model.RevokeDialogArgs
35
36 @Composable
WearAppPermissionGroupsScreennull37 fun WearAppPermissionGroupsScreen(helper: WearAppPermissionGroupsHelper) {
38 val packagePermGroups = helper.viewModel.packagePermGroupsLiveData.observeAsState(null)
39 val autoRevoke = helper.viewModel.autoRevokeLiveData.observeAsState(null)
40 val appPermissionUsages = helper.wearViewModel.appPermissionUsages.observeAsState(emptyList())
41 val showRevokeDialog = helper.revokeDialogViewModel.showDialogLiveData.observeAsState(false)
42 var isLoading by remember { mutableStateOf(true) }
43
44 Box {
45 WearAppPermissionGroupsContent(
46 isLoading,
47 helper.getPermissionGroupChipParams(appPermissionUsages.value),
48 helper.getAutoRevokeChipParam(autoRevoke.value)
49 )
50 RevokeDialog(
51 showDialog = showRevokeDialog.value,
52 args = helper.revokeDialogViewModel.revokeDialogArgs
53 )
54 }
55
56 if (isLoading && !packagePermGroups.value.isNullOrEmpty()) {
57 isLoading = false
58 }
59 }
60
61 @Composable
WearAppPermissionGroupsContentnull62 internal fun WearAppPermissionGroupsContent(
63 isLoading: Boolean,
64 permissionGroupChipParams: List<PermissionGroupChipParam>,
65 autoRevokeChipParam: AutoRevokeChipParam?
66 ) {
67 ScrollableScreen(title = stringResource(R.string.app_permissions), isLoading = isLoading) {
68 if (permissionGroupChipParams.isEmpty()) {
69 item { Chip(label = stringResource(R.string.no_permissions), onClick = {}) }
70 } else {
71 for (info in permissionGroupChipParams) {
72 item {
73 if (info.checked != null) {
74 ToggleChip(
75 checked = info.checked,
76 label = info.label,
77 enabled = info.enabled,
78 toggleControl = ToggleChipToggleControl.Switch,
79 onCheckedChanged = info.onCheckedChanged
80 )
81 } else {
82 Chip(
83 label = info.label,
84 labelMaxLines = Integer.MAX_VALUE,
85 secondaryLabel = info.summary?.let { info.summary },
86 secondaryLabelMaxLines = Integer.MAX_VALUE,
87 enabled = info.enabled,
88 onClick = info.onClick
89 )
90 }
91 }
92 }
93 autoRevokeChipParam?.let {
94 if (it.visible) {
95 item {
96 ToggleChip(
97 checked = it.checked,
98 label = stringResource(it.labelRes),
99 labelMaxLine = 3,
100 toggleControl = ToggleChipToggleControl.Switch,
101 onCheckedChanged = it.onCheckedChanged
102 )
103 }
104 }
105 }
106 }
107 }
108 }
109
110 @Composable
RevokeDialognull111 internal fun RevokeDialog(showDialog: Boolean, args: RevokeDialogArgs?) {
112 args?.let {
113 AlertDialog(
114 showDialog = showDialog,
115 message = stringResource(it.messageId),
116 onOKButtonClick = it.onOkButtonClick,
117 onCancelButtonClick = it.onCancelButtonClick,
118 scalingLazyListState = rememberScalingLazyListState()
119 )
120 }
121 }
122