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