diff --git a/src/com/android/settings/spa/SettingsSpaEnvironment.kt b/src/com/android/settings/spa/SettingsSpaEnvironment.kt index 5131dde7b59..bf15ddfa7f3 100644 --- a/src/com/android/settings/spa/SettingsSpaEnvironment.kt +++ b/src/com/android/settings/spa/SettingsSpaEnvironment.kt @@ -32,6 +32,9 @@ import com.android.settings.spa.development.UsageStatsPageProvider import com.android.settings.spa.home.HomePageProvider import com.android.settings.spa.notification.AppListNotificationsPageProvider import com.android.settings.spa.notification.NotificationMainPageProvider +import com.android.settings.spa.system.AppLanguagesPageProvider +import com.android.settings.spa.system.LanguageAndInputPageProvider +import com.android.settings.spa.system.SystemMainPageProvider import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProviderRepository import com.android.settingslib.spa.framework.common.SpaEnvironment @@ -59,6 +62,9 @@ open class SettingsSpaEnvironment(context: Context) : SpaEnvironment(context) { SpecialAppAccessPageProvider, NotificationMainPageProvider, AppListNotificationsPageProvider, + SystemMainPageProvider, + LanguageAndInputPageProvider, + AppLanguagesPageProvider, UsageStatsPageProvider, ) + togglePermissionAppListTemplate.createPageProviders(), rootPages = listOf( diff --git a/src/com/android/settings/spa/home/HomePage.kt b/src/com/android/settings/spa/home/HomePage.kt index f1008966922..3c16f5a0111 100644 --- a/src/com/android/settings/spa/home/HomePage.kt +++ b/src/com/android/settings/spa/home/HomePage.kt @@ -22,6 +22,7 @@ import androidx.compose.ui.res.stringResource import com.android.settings.R import com.android.settings.spa.app.AppsMainPageProvider import com.android.settings.spa.notification.NotificationMainPageProvider +import com.android.settings.spa.system.SystemMainPageProvider import com.android.settingslib.spa.framework.common.SettingsEntry import com.android.settingslib.spa.framework.common.SettingsPage import com.android.settingslib.spa.framework.common.SettingsPageProvider @@ -48,5 +49,6 @@ private fun HomePage() { HomeScaffold(title = stringResource(R.string.settings_label)) { AppsMainPageProvider.EntryItem() NotificationMainPageProvider.EntryItem() + SystemMainPageProvider.EntryItem() } } diff --git a/src/com/android/settings/spa/system/AppLanguages.kt b/src/com/android/settings/spa/system/AppLanguages.kt new file mode 100644 index 00000000000..3c875f19893 --- /dev/null +++ b/src/com/android/settings/spa/system/AppLanguages.kt @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.spa.system + +import android.content.Intent +import android.net.Uri +import android.os.Bundle +import androidx.compose.runtime.Composable +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settings.localepicker.AppLocalePickerActivity +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.framework.compose.rememberContext +import com.android.settingslib.spa.framework.compose.toState +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spaprivileged.template.app.AppListItem +import com.android.settingslib.spaprivileged.template.app.AppListItemModel +import com.android.settingslib.spaprivileged.template.app.AppListPage + +object AppLanguagesPageProvider : SettingsPageProvider { + override val name = "AppLanguages" + + @Composable + override fun Page(arguments: Bundle?) { + AppListPage( + title = stringResource(R.string.app_locales_picker_menu_title), + listModel = rememberContext(::AppLanguagesListModel), + ) { + AppLanguageItem(it) + } + } + + @Composable + fun EntryItem() { + Preference(object : PreferenceModel { + override val title = stringResource(R.string.app_locales_picker_menu_title) + override val summary = stringResource(R.string.app_locale_picker_summary).toState() + override val onClick = navigator(name) + }) + } +} + +@Composable +private fun AppLanguageItem(itemModel: AppListItemModel) { + val context = LocalContext.current + AppListItem( + itemModel = itemModel, + onClick = { + val intent = Intent(context, AppLocalePickerActivity::class.java).apply { + setData(Uri.parse("package:${itemModel.record.app.packageName}")) + putExtra("uid", itemModel.record.app.uid) + } + context.startActivity(intent) + } + ) +} \ No newline at end of file diff --git a/src/com/android/settings/spa/system/AppLanguagesListModel.kt b/src/com/android/settings/spa/system/AppLanguagesListModel.kt new file mode 100644 index 00000000000..15a0b859243 --- /dev/null +++ b/src/com/android/settings/spa/system/AppLanguagesListModel.kt @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.spa.system + +import android.content.Context +import android.content.pm.ApplicationInfo +import android.content.pm.PackageManager +import androidx.compose.runtime.Composable +import androidx.compose.runtime.State +import androidx.compose.runtime.remember +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settings.applications.AppLocaleUtil +import com.android.settings.applications.appinfo.AppLocaleDetails +import com.android.settingslib.applications.ApplicationsState +import com.android.settingslib.applications.ApplicationsState.AppEntry +import com.android.settingslib.spa.framework.compose.collectAsStateWithLifecycle +import com.android.settingslib.spa.framework.util.asyncMapItem +import com.android.settingslib.spaprivileged.model.app.AppListModel +import com.android.settingslib.spaprivileged.model.app.AppRecord +import com.android.settingslib.spaprivileged.model.app.userId +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine +import kotlinx.coroutines.flow.flow +import kotlinx.coroutines.flow.map + +data class AppLanguagesRecord( + override val app: ApplicationInfo, + val isAppLocaleSupported: Boolean +) : AppRecord + +class AppLanguagesListModel(private val context: Context) : AppListModel { + private val now = System.currentTimeMillis() + private val packageManager = context.packageManager + + override fun transform(userIdFlow: Flow, appListFlow: Flow>) = + userIdFlow.map { userId -> + packageManager.queryIntentActivitiesAsUser( + AppLocaleUtil.LAUNCHER_ENTRY_INTENT, + PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()), + userId, + ) + }.combine(appListFlow) { resolveInfos, appList -> + appList.map { app -> + AppLanguagesRecord(app, + AppLocaleUtil.canDisplayLocaleUi(context, + app.packageName, resolveInfos)) + } + } + + override fun filter( + userIdFlow: Flow, + option: Int, + recordListFlow: Flow> + ) = recordListFlow.map { recordList -> + recordList.filter { it.isAppLocaleSupported } + } + + @Composable + override fun getSummary(option: Int, record: AppLanguagesRecord): State? = + remember(record.app) { + flow { + emit(getSummary(record.app)) + } + }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder)) + + private fun getSummary(app: ApplicationInfo): String = + AppLocaleDetails.getAppDefaultLocale(context, app.packageName)?.let { + AppLocaleDetails.getSummary(context, app).toString() + } ?: context.getString(R.string.preference_of_system_locale_summary) +} \ No newline at end of file diff --git a/src/com/android/settings/spa/system/LanguageAndInputPageProvider.kt b/src/com/android/settings/spa/system/LanguageAndInputPageProvider.kt new file mode 100644 index 00000000000..06fe3927f01 --- /dev/null +++ b/src/com/android/settings/spa/system/LanguageAndInputPageProvider.kt @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.spa.system + +import android.os.Bundle +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Language +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.framework.compose.toState +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spa.widget.scaffold.RegularScaffold +import com.android.settingslib.spa.widget.ui.SettingsIcon + +object LanguageAndInputPageProvider : SettingsPageProvider { + override val name = "LanguageAndInput" + + @Composable + override fun Page(arguments: Bundle?) { + LanguageAndInput() + } + + @Composable + fun EntryItem() { + Preference(object : PreferenceModel { + override val title = stringResource(R.string.language_settings) + override val summary = stringResource(R.string.language_settings).toState() + override val onClick = navigator(name) + override val icon = @Composable { + SettingsIcon(imageVector = Icons.Outlined.Language) + } + }) + } + +} + +@Composable +private fun LanguageAndInput() { + RegularScaffold(title = stringResource(R.string.language_settings)) { + AppLanguagesPageProvider.EntryItem() + } +} \ No newline at end of file diff --git a/src/com/android/settings/spa/system/SystemMain.kt b/src/com/android/settings/spa/system/SystemMain.kt new file mode 100644 index 00000000000..2832468a1c0 --- /dev/null +++ b/src/com/android/settings/spa/system/SystemMain.kt @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.spa.system + +import android.os.Bundle +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Info +import androidx.compose.runtime.Composable +import androidx.compose.ui.res.stringResource +import com.android.settings.R +import com.android.settingslib.spa.framework.common.SettingsEntryBuilder +import com.android.settingslib.spa.framework.common.SettingsPage +import com.android.settingslib.spa.framework.common.SettingsPageProvider +import com.android.settingslib.spa.framework.compose.navigator +import com.android.settingslib.spa.framework.compose.toState +import com.android.settingslib.spa.widget.preference.Preference +import com.android.settingslib.spa.widget.preference.PreferenceModel +import com.android.settingslib.spa.widget.scaffold.RegularScaffold +import com.android.settingslib.spa.widget.ui.SettingsIcon + +object SystemMainPageProvider : SettingsPageProvider { + override val name = "SystemMain" + + @Composable + override fun Page(arguments: Bundle?) { + SystemMain() + } + + @Composable + fun EntryItem() { + Preference(object : PreferenceModel { + override val title = stringResource(R.string.header_category_system) + override val summary = stringResource(R.string.system_dashboard_summary).toState() + override val onClick = navigator(name) + override val icon = @Composable { + SettingsIcon(imageVector = Icons.Outlined.Info) + } + }) + } + + fun buildInjectEntry() = + SettingsEntryBuilder.createInject(owner = SettingsPage.create(name)).setIsAllowSearch(false) +} + +@Composable +private fun SystemMain() { + RegularScaffold(title = stringResource(R.string.header_category_system)) { + LanguageAndInputPageProvider.EntryItem() + } +} \ No newline at end of file