1 /*
<lambda>null2  * Copyright (C) 2022 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.settings.spa.app.appinfo
18 
19 import android.content.Context
20 import android.content.pm.ApplicationInfo
21 import androidx.compose.foundation.layout.Column
22 import androidx.compose.foundation.layout.padding
23 import androidx.compose.material3.AlertDialog
24 import androidx.compose.material3.Text
25 import androidx.compose.runtime.Composable
26 import androidx.compose.runtime.State
27 import androidx.compose.runtime.getValue
28 import androidx.compose.runtime.mutableStateOf
29 import androidx.compose.runtime.remember
30 import androidx.compose.runtime.saveable.rememberSaveable
31 import androidx.compose.runtime.setValue
32 import androidx.compose.ui.Modifier
33 import androidx.compose.ui.platform.LocalContext
34 import androidx.compose.ui.res.stringResource
35 import androidx.lifecycle.compose.collectAsStateWithLifecycle
36 import com.android.settings.R
37 import com.android.settings.Utils
38 import com.android.settingslib.spa.framework.theme.SettingsDimension
39 import com.android.settingslib.spa.widget.preference.Preference
40 import com.android.settingslib.spa.widget.preference.PreferenceModel
41 import com.android.settingslib.spaprivileged.framework.common.asUser
42 import com.android.settingslib.spaprivileged.model.app.userHandle
43 import kotlinx.coroutines.Dispatchers
44 import kotlinx.coroutines.flow.flow
45 import kotlinx.coroutines.flow.flowOn
46 import kotlinx.coroutines.flow.map
47 
48 @Composable
49 fun InstantAppDomainsPreference(app: ApplicationInfo) {
50     val context = LocalContext.current
51     if (!app.isInstantApp) return
52 
53     val presenter = remember { InstantAppDomainsPresenter(context, app) }
54     var openDialog by rememberSaveable { mutableStateOf(false) }
55 
56     val summary by presenter.summaryFlow.collectAsStateWithLifecycle(
57         initialValue = stringResource(R.string.summary_placeholder),
58     )
59     Preference(object : PreferenceModel {
60         override val title = stringResource(R.string.app_launch_supported_domain_urls_title)
61         override val summary = { summary }
62         override val onClick = { openDialog = true }
63     })
64 
65     val domainsState = presenter.domainsFlow.collectAsStateWithLifecycle(initialValue = emptySet())
66     if (openDialog) {
67         Dialog(domainsState) {
68             openDialog = false
69         }
70     }
71 }
72 
73 @Composable
Dialognull74 private fun Dialog(domainsState: State<Set<String>>, onDismissRequest: () -> Unit) {
75     AlertDialog(
76         onDismissRequest = onDismissRequest,
77         confirmButton = {},
78         title = {
79             Text(stringResource(R.string.app_launch_supported_domain_urls_title))
80         },
81         text = {
82             Column {
83                 domainsState.value.forEach { domain ->
84                     Text(
85                         text = domain,
86                         modifier = Modifier.padding(vertical = SettingsDimension.itemPaddingAround),
87                     )
88                 }
89             }
90         },
91     )
92 }
93 
94 private class InstantAppDomainsPresenter(
95     private val context: Context,
96     private val app: ApplicationInfo,
97 ) {
98     private val userContext = context.asUser(app.userHandle)
99     private val userPackageManager = userContext.packageManager
100 
<lambda>null101     val domainsFlow = flow {
102         emit(Utils.getHandledDomains(userPackageManager, app.packageName))
103     }.flowOn(Dispatchers.IO)
104 
entriesnull105     val summaryFlow = domainsFlow.map { entries ->
106         when (entries.size) {
107             0 -> context.getString(R.string.domain_urls_summary_none)
108             1 -> context.getString(R.string.domain_urls_summary_one, entries.first())
109             else -> context.getString(R.string.domain_urls_summary_some, entries.first())
110         }
111     }.flowOn(Dispatchers.IO)
112 }
113