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 com.android.settings.R
36 import com.android.settings.Utils
37 import androidx.lifecycle.compose.ExperimentalLifecycleComposeApi
38 import androidx.lifecycle.compose.collectAsStateWithLifecycle
39 import com.android.settingslib.spa.framework.theme.SettingsDimension
40 import com.android.settingslib.spa.widget.preference.Preference
41 import com.android.settingslib.spa.widget.preference.PreferenceModel
42 import com.android.settingslib.spaprivileged.framework.common.asUser
43 import com.android.settingslib.spaprivileged.model.app.userHandle
44 import kotlinx.coroutines.Dispatchers
45 import kotlinx.coroutines.flow.flow
46 import kotlinx.coroutines.flow.flowOn
47 import kotlinx.coroutines.flow.map
48
49 @OptIn(ExperimentalLifecycleComposeApi::class)
50 @Composable
51 fun InstantAppDomainsPreference(app: ApplicationInfo) {
52 val context = LocalContext.current
53 if (!app.isInstantApp) return
54
55 val presenter = remember { InstantAppDomainsPresenter(context, app) }
56 var openDialog by rememberSaveable { mutableStateOf(false) }
57
58 Preference(object : PreferenceModel {
59 override val title = stringResource(R.string.app_launch_supported_domain_urls_title)
60 override val summary = presenter.summaryFlow.collectAsStateWithLifecycle(
61 initialValue = stringResource(R.string.summary_placeholder),
62 )
63 override val onClick = { openDialog = true }
64 })
65
66 val domainsState = presenter.domainsFlow.collectAsStateWithLifecycle(initialValue = emptySet())
67 if (openDialog) {
68 Dialog(domainsState) {
69 openDialog = false
70 }
71 }
72 }
73
74 @Composable
Dialognull75 private fun Dialog(domainsState: State<Set<String>>, onDismissRequest: () -> Unit) {
76 AlertDialog(
77 onDismissRequest = onDismissRequest,
78 confirmButton = {},
79 title = {
80 Text(stringResource(R.string.app_launch_supported_domain_urls_title))
81 },
82 text = {
83 Column {
84 domainsState.value.forEach { domain ->
85 Text(
86 text = domain,
87 modifier = Modifier.padding(vertical = SettingsDimension.itemPaddingAround),
88 )
89 }
90 }
91 },
92 )
93 }
94
95 private class InstantAppDomainsPresenter(
96 private val context: Context,
97 private val app: ApplicationInfo,
98 ) {
99 private val userContext = context.asUser(app.userHandle)
100 private val userPackageManager = userContext.packageManager
101
<lambda>null102 val domainsFlow = flow {
103 emit(Utils.getHandledDomains(userPackageManager, app.packageName))
104 }.flowOn(Dispatchers.IO)
105
entriesnull106 val summaryFlow = domainsFlow.map { entries ->
107 when (entries.size) {
108 0 -> context.getString(R.string.domain_urls_summary_none)
109 1 -> context.getString(R.string.domain_urls_summary_one, entries.first())
110 else -> context.getString(R.string.domain_urls_summary_some, entries.first())
111 }
112 }.flowOn(Dispatchers.IO)
113 }
114