1 /*
2 * 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.Intent
21 import android.content.pm.ApplicationInfo
22 import android.content.pm.PackageManager
23 import android.content.pm.PackageManager.ResolveInfoFlags
24 import android.net.Uri
25 import androidx.compose.runtime.Composable
26 import androidx.compose.runtime.getValue
27 import androidx.compose.runtime.remember
28 import androidx.compose.ui.platform.LocalContext
29 import androidx.compose.ui.res.stringResource
30 import androidx.lifecycle.compose.collectAsStateWithLifecycle
31 import com.android.settings.R
32 import com.android.settings.applications.AppInfoBase
33 import com.android.settings.applications.AppLocaleUtil
34 import com.android.settings.applications.appinfo.AppLocaleDetails
35 import com.android.settings.localepicker.AppLocalePickerActivity
36 import com.android.settingslib.spa.widget.preference.Preference
37 import com.android.settingslib.spa.widget.preference.PreferenceModel
38 import com.android.settingslib.spaprivileged.model.app.userHandle
39 import com.android.settingslib.spaprivileged.model.app.userId
40 import kotlinx.coroutines.Dispatchers
41 import kotlinx.coroutines.flow.flow
42 import kotlinx.coroutines.withContext
43
44 @Composable
AppLocalePreferencenull45 fun AppLocalePreference(app: ApplicationInfo) {
46 val context = LocalContext.current
47 val presenter = remember { AppLocalePresenter(context, app) }
48 if (!presenter.isAvailableFlow.collectAsStateWithLifecycle(initialValue = false).value) return
49
50 val summary by presenter.summaryFlow.collectAsStateWithLifecycle(
51 initialValue = stringResource(R.string.summary_placeholder),
52 )
53 Preference(object : PreferenceModel {
54 override val title = stringResource(R.string.app_locale_preference_title)
55 override val summary = { summary }
56 override val onClick = presenter::startActivity
57 })
58 }
59
60 private class AppLocalePresenter(
61 private val context: Context,
62 private val app: ApplicationInfo,
63 ) {
64 private val packageManager = context.packageManager
65
<lambda>null66 val isAvailableFlow = flow { emit(isAvailable()) }
67
<lambda>null68 private suspend fun isAvailable(): Boolean = withContext(Dispatchers.IO) {
69 val resolveInfos = packageManager.queryIntentActivitiesAsUser(
70 AppLocaleUtil.LAUNCHER_ENTRY_INTENT,
71 ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
72 app.userId,
73 )
74 AppLocaleUtil.canDisplayLocaleUi(context, app, resolveInfos)
75 }
76
<lambda>null77 val summaryFlow = flow { emit(getSummary()) }
78
<lambda>null79 private suspend fun getSummary() = withContext(Dispatchers.IO) {
80 AppLocaleDetails.getSummary(context, app).toString()
81 }
82
startActivitynull83 fun startActivity() {
84 val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
85 data = Uri.parse("package:" + app.packageName)
86 putExtra(AppInfoBase.ARG_PACKAGE_UID, app.uid)
87 }
88 context.startActivityAsUser(intent, app.userHandle)
89 }
90 }
91