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 android.icu.text.MessageFormat
20 import androidx.compose.runtime.Composable
21 import androidx.compose.runtime.livedata.observeAsState
22 import androidx.compose.ui.res.stringResource
23 import androidx.wear.compose.material.Text
24 import com.android.permissioncontroller.R
25 import com.android.permissioncontroller.hibernation.isHibernationEnabled
26 import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod
27 import com.android.permissioncontroller.permission.ui.model.UnusedAppsViewModel.UnusedPeriod.Companion.allPeriods
28 import com.android.permissioncontroller.permission.ui.wear.elements.Chip
29 import com.android.permissioncontroller.permission.ui.wear.elements.Icon
30 import com.android.permissioncontroller.permission.ui.wear.elements.ScrollableScreen
31 import com.android.permissioncontroller.permission.ui.wear.model.WearUnusedAppsViewModel
32 
33 @Composable
WearUnusedAppsScreennull34 fun WearUnusedAppsScreen(viewModel: WearUnusedAppsViewModel) {
35     val loading = viewModel.loadingLiveData.observeAsState(true)
36     val unusedPeriodCategoryVisibilities =
37         viewModel.unusedPeriodCategoryVisibilitiesLiveData.observeAsState(emptyList())
38     val infoMsgCategoryVisibility =
39         viewModel.infoMsgCategoryVisibilityLiveData.observeAsState(false)
40     val unusedAppChips = viewModel.unusedAppChipsLiveData.observeAsState(mapOf())
41 
42     ScrollableScreen(
43         showTimeText = true,
44         title = getScreenTitle(),
45         isLoading = loading.value,
46         subtitle = getSubTitle(!infoMsgCategoryVisibility.value)
47     ) {
48         for (period in allPeriods) {
49             if (!unusedAppChips.value.containsKey(period)) {
50                 continue
51             }
52             item {
53                 val pos = posByPeriod(period)
54                 if (unusedPeriodCategoryVisibilities.value.getOrElse(pos) { false }) {
55                     Text(text = categoryTitleByPeriod(period))
56                 }
57             }
58             for (unusedAppChip in unusedAppChips.value[period]!!.values) {
59                 item {
60                     Chip(
61                         label = unusedAppChip.label,
62                         secondaryLabel = unusedAppChip.summary,
63                         icon = unusedAppChip.icon,
64                         iconContentDescription = unusedAppChip.contentDescription,
65                         onClick = unusedAppChip.onClick
66                     )
67                 }
68             }
69         }
70         // For info_msg_category
71         if (infoMsgCategoryVisibility.value) {
72             item { Icon(icon = R.drawable.ic_info_outline, contentDescription = null) }
73             if (isHibernationEnabled()) {
74                 item { Text(text = stringResource(R.string.unused_apps_page_summary)) }
75             } else {
76                 item { Text(text = stringResource(R.string.auto_revoked_apps_page_summary)) }
77                 item { Text(text = stringResource(R.string.auto_revoke_open_app_message)) }
78             }
79         }
80     }
81 }
82 
83 @Composable
getScreenTitlenull84 private fun getScreenTitle() =
85     if (isHibernationEnabled()) {
86         stringResource(R.string.unused_apps_page_title)
87     } else {
88         stringResource(R.string.permission_removed_page_title)
89     }
90 
91 @Composable
getSubTitlenull92 private fun getSubTitle(shouldShow: Boolean) =
93     if (shouldShow) {
94         stringResource(R.string.no_unused_apps)
95     } else {
96         null
97     }
98 
99 @Composable
posByPeriodnull100 private fun posByPeriod(period: UnusedPeriod) =
101     when (period) {
102         UnusedPeriod.ONE_MONTH -> 0
103         UnusedPeriod.THREE_MONTHS -> 1
104         UnusedPeriod.SIX_MONTHS -> 2
105     }
106 
107 @Composable
categoryTitleByPeriodnull108 private fun categoryTitleByPeriod(period: UnusedPeriod) =
109     MessageFormat.format(
110         stringResource(R.string.last_opened_category_title),
111         mapOf("count" to period.months)
112     )
113