Move AppItem into AppListModel

Follows the api changes in Spa privileged lib.

Bug: 260660819
Test: Unit test
Test: Manually with Settings
Change-Id: Ieec1035070cc532eedcd1511c5b347e04099a9fb
This commit is contained in:
Chaohui Wang
2022-12-15 12:30:44 +08:00
parent c8b31a5170
commit 1445d985bb
7 changed files with 78 additions and 95 deletions

View File

@@ -36,6 +36,7 @@ import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.template.app.AppList import com.android.settingslib.spaprivileged.template.app.AppList
import com.android.settingslib.spaprivileged.template.app.AppListInput import com.android.settingslib.spaprivileged.template.app.AppListInput
import com.android.settingslib.spaprivileged.template.app.AppListItem import com.android.settingslib.spaprivileged.template.app.AppListItem
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import com.android.settingslib.spaprivileged.template.app.AppListPage import com.android.settingslib.spaprivileged.template.app.AppListPage
import com.android.settingslib.spaprivileged.template.app.getStorageSize import com.android.settingslib.spaprivileged.template.app.getStorageSize
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -70,9 +71,7 @@ fun AllAppListPage(
showInstantApps = true, showInstantApps = true,
moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) }, moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
appList = appList, appList = appList,
) { )
AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
}
} }
data class AppRecordWithSize( data class AppRecordWithSize(
@@ -88,4 +87,9 @@ class AllAppListModel(
@Composable @Composable
override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getSummary() override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getSummary()
@Composable
override fun AppListItemModel<AppRecordWithSize>.AppItem() {
AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
}
} }

View File

@@ -21,11 +21,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import com.android.settings.R import com.android.settings.R
import com.android.settingslib.spa.framework.common.SettingsPageProvider 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.rememberContext
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.AppListPage import com.android.settingslib.spaprivileged.template.app.AppListPage
object UsageStatsPageProvider : SettingsPageProvider { object UsageStatsPageProvider : SettingsPageProvider {
@@ -37,14 +33,6 @@ object UsageStatsPageProvider : SettingsPageProvider {
title = stringResource(R.string.testing_usage_stats), title = stringResource(R.string.testing_usage_stats),
listModel = rememberContext(::UsageStatsListModel), listModel = rememberContext(::UsageStatsListModel),
primaryUserOnly = true, primaryUserOnly = true,
) { AppListItem {} } )
}
@Composable
fun EntryItem() {
Preference(object : PreferenceModel {
override val title = stringResource(R.string.testing_usage_stats)
override val onClick = navigator(name)
})
} }
} }

View File

@@ -16,27 +16,17 @@
package com.android.settings.spa.notification package com.android.settings.spa.notification
import android.app.settings.SettingsEnums
import android.content.Context
import android.content.pm.ApplicationInfo
import android.os.Bundle import android.os.Bundle
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.produceState
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import com.android.settings.R import com.android.settings.R
import com.android.settings.applications.AppInfoBase
import com.android.settings.notification.app.AppNotificationSettings
import com.android.settingslib.spa.framework.common.SettingsPageProvider import com.android.settingslib.spa.framework.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.rememberContext import com.android.settingslib.spa.framework.compose.rememberContext
import com.android.settingslib.spa.framework.compose.toState import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import com.android.settingslib.spaprivileged.template.app.AppListPage import com.android.settingslib.spaprivileged.template.app.AppListPage
import com.android.settingslib.spaprivileged.template.app.AppListSwitchItem
object AppListNotificationsPageProvider : SettingsPageProvider { object AppListNotificationsPageProvider : SettingsPageProvider {
override val name = "AppListNotifications" override val name = "AppListNotifications"
@@ -46,7 +36,7 @@ object AppListNotificationsPageProvider : SettingsPageProvider {
AppListPage( AppListPage(
title = stringResource(R.string.app_notifications_title), title = stringResource(R.string.app_notifications_title),
listModel = rememberContext(::AppNotificationsListModel), listModel = rememberContext(::AppNotificationsListModel),
) { AppNotificationsItem() } )
} }
@Composable @Composable
@@ -58,32 +48,3 @@ object AppListNotificationsPageProvider : SettingsPageProvider {
}) })
} }
} }
@Composable
private fun AppListItemModel<AppNotificationsRecord>.AppNotificationsItem() {
val appNotificationsRepository = rememberContext(::AppNotificationRepository)
val context = LocalContext.current
AppListSwitchItem(
onClick = {
navigateToAppNotificationSettings(
context = context,
app = record.app,
)
},
checked = record.controller.isEnabled.observeAsState(),
changeable = produceState(initialValue = false) {
value = appNotificationsRepository.isChangeable(record.app)
},
onCheckedChange = record.controller::setEnabled,
)
}
private fun navigateToAppNotificationSettings(context: Context, app: ApplicationInfo) {
AppInfoBase.startAppInfoFragment(
AppNotificationSettings::class.java,
context.getString(R.string.notifications_title),
app,
context,
SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS,
)
}

View File

@@ -16,11 +16,16 @@
package com.android.settings.spa.notification package com.android.settings.spa.notification
import android.app.settings.SettingsEnums
import android.content.Context import android.content.Context
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.icu.text.RelativeDateTimeFormatter import android.icu.text.RelativeDateTimeFormatter
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.produceState
import com.android.settings.R import com.android.settings.R
import com.android.settings.applications.AppInfoBase
import com.android.settings.notification.app.AppNotificationSettings
import com.android.settings.spa.notification.SpinnerItem.Companion.toSpinnerItem import com.android.settings.spa.notification.SpinnerItem.Companion.toSpinnerItem
import com.android.settingslib.spa.framework.compose.stateOf import com.android.settingslib.spa.framework.compose.stateOf
import com.android.settingslib.spa.framework.util.asyncFilter import com.android.settingslib.spa.framework.util.asyncFilter
@@ -28,6 +33,8 @@ import com.android.settingslib.spa.framework.util.asyncForEach
import com.android.settingslib.spaprivileged.model.app.AppEntry import com.android.settingslib.spaprivileged.model.app.AppEntry
import com.android.settingslib.spaprivileged.model.app.AppListModel import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import com.android.settingslib.spaprivileged.template.app.AppListSwitchItem
import com.android.settingslib.utils.StringUtil import com.android.settingslib.utils.StringUtil
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@@ -114,6 +121,28 @@ class AppNotificationsListModel(
) )
} }
} }
@Composable
override fun AppListItemModel<AppNotificationsRecord>.AppItem() {
AppListSwitchItem(
onClick = { navigateToAppNotificationSettings(app = record.app) },
checked = record.controller.isEnabled.observeAsState(),
changeable = produceState(initialValue = false) {
value = repository.isChangeable(record.app)
},
onCheckedChange = record.controller::setEnabled,
)
}
private fun navigateToAppNotificationSettings(app: ApplicationInfo) {
AppInfoBase.startAppInfoFragment(
AppNotificationSettings::class.java,
context.getString(R.string.notifications_title),
app,
context,
SettingsEnums.MANAGE_APPLICATIONS_NOTIFICATIONS,
)
}
} }
private enum class SpinnerItem(val stringResId: Int) { private enum class SpinnerItem(val stringResId: Int) {

View File

@@ -16,17 +16,13 @@
package com.android.settings.spa.system package com.android.settings.spa.system
import android.content.Intent
import android.net.Uri
import android.os.Bundle import android.os.Bundle
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import com.android.settings.R 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.common.SettingsPageProvider
import com.android.settingslib.spa.framework.compose.navigator import com.android.settingslib.spa.framework.compose.navigator
import com.android.settingslib.spa.framework.compose.rememberContext import com.android.settingslib.spa.framework.compose.rememberContext
@@ -35,8 +31,6 @@ import com.android.settingslib.spa.framework.theme.SettingsDimension
import com.android.settingslib.spa.widget.preference.Preference import com.android.settingslib.spa.widget.preference.Preference
import com.android.settingslib.spa.widget.preference.PreferenceModel import com.android.settingslib.spa.widget.preference.PreferenceModel
import com.android.settingslib.spa.widget.ui.SettingsBody import com.android.settingslib.spa.widget.ui.SettingsBody
import com.android.settingslib.spaprivileged.template.app.AppListItem
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import com.android.settingslib.spaprivileged.template.app.AppListPage import com.android.settingslib.spaprivileged.template.app.AppListPage
object AppLanguagesPageProvider : SettingsPageProvider { object AppLanguagesPageProvider : SettingsPageProvider {
@@ -52,7 +46,7 @@ object AppLanguagesPageProvider : SettingsPageProvider {
SettingsBody(stringResource(R.string.desc_app_locale_selection_supported)) SettingsBody(stringResource(R.string.desc_app_locale_selection_supported))
} }
}, },
) { AppLanguageItem() } )
} }
@Composable @Composable
@@ -64,15 +58,3 @@ object AppLanguagesPageProvider : SettingsPageProvider {
}) })
} }
} }
@Composable
private fun AppListItemModel<AppLanguagesRecord>.AppLanguageItem() {
val context = LocalContext.current
AppListItem {
val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
data = Uri.parse("package:${record.app.packageName}")
putExtra("uid", record.app.uid)
}
context.startActivity(intent)
}
}

View File

@@ -17,8 +17,10 @@
package com.android.settings.spa.system package com.android.settings.spa.system
import android.content.Context import android.content.Context
import android.content.Intent
import android.content.pm.ApplicationInfo import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.net.Uri
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.State import androidx.compose.runtime.State
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
@@ -28,56 +30,73 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.settings.R import com.android.settings.R
import com.android.settings.applications.AppLocaleUtil import com.android.settings.applications.AppLocaleUtil
import com.android.settings.applications.appinfo.AppLocaleDetails import com.android.settings.applications.appinfo.AppLocaleDetails
import com.android.settings.localepicker.AppLocalePickerActivity
import com.android.settingslib.spa.framework.util.filterItem
import com.android.settingslib.spaprivileged.model.app.AppListModel import com.android.settingslib.spaprivileged.model.app.AppListModel
import com.android.settingslib.spaprivileged.model.app.AppRecord import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.template.app.AppListItem
import com.android.settingslib.spaprivileged.template.app.AppListItemModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
data class AppLanguagesRecord( data class AppLanguagesRecord(
override val app: ApplicationInfo, override val app: ApplicationInfo,
val isAppLocaleSupported: Boolean val isAppLocaleSupported: Boolean,
) : AppRecord ) : AppRecord
class AppLanguagesListModel(private val context: Context) : AppListModel<AppLanguagesRecord> { class AppLanguagesListModel(private val context: Context) : AppListModel<AppLanguagesRecord> {
private val now = System.currentTimeMillis()
private val packageManager = context.packageManager private val packageManager = context.packageManager
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) = override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
userIdFlow.map { userId -> userIdFlow.map { userId ->
packageManager.queryIntentActivitiesAsUser( packageManager.queryIntentActivitiesAsUser(
AppLocaleUtil.LAUNCHER_ENTRY_INTENT, AppLocaleUtil.LAUNCHER_ENTRY_INTENT,
PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()), PackageManager.ResolveInfoFlags.of(PackageManager.GET_META_DATA.toLong()),
userId, userId,
) )
}.combine(appListFlow) { resolveInfos, appList -> }.combine(appListFlow) { resolveInfos, appList ->
appList.map { app -> appList.map { app ->
AppLanguagesRecord(app, AppLanguagesRecord(
AppLocaleUtil.canDisplayLocaleUi(context, app = app,
app, resolveInfos)) isAppLocaleSupported = AppLocaleUtil.canDisplayLocaleUi(
context, app, resolveInfos
),
)
} }
} }
override fun filter( override fun filter(
userIdFlow: Flow<Int>, userIdFlow: Flow<Int>,
option: Int, option: Int,
recordListFlow: Flow<List<AppLanguagesRecord>> recordListFlow: Flow<List<AppLanguagesRecord>>,
) = recordListFlow.map { recordList -> ) = recordListFlow.filterItem { it.isAppLocaleSupported }
recordList.filter { it.isAppLocaleSupported }
}
@OptIn(ExperimentalLifecycleComposeApi::class) @OptIn(ExperimentalLifecycleComposeApi::class)
@Composable @Composable
override fun getSummary(option: Int, record: AppLanguagesRecord): State<String>? = override fun getSummary(option: Int, record: AppLanguagesRecord): State<String> =
remember(record.app) { remember(record.app) {
flow { flow {
emit(getSummary(record.app)) emit(getSummary(record.app))
} }.flowOn(Dispatchers.IO)
}.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder)) }.collectAsStateWithLifecycle(initialValue = stringResource(R.string.summary_placeholder))
private fun getSummary(app: ApplicationInfo): String = private fun getSummary(app: ApplicationInfo): String =
AppLocaleDetails.getAppDefaultLocale(context, app.packageName)?.let { AppLocaleDetails.getAppDefaultLocale(context, app.packageName)?.let {
AppLocaleDetails.getSummary(context, app).toString() AppLocaleDetails.getSummary(context, app).toString()
} ?: context.getString(R.string.preference_of_system_locale_summary) } ?: context.getString(R.string.preference_of_system_locale_summary)
}
@Composable
override fun AppListItemModel<AppLanguagesRecord>.AppItem() {
AppListItem {
val intent = Intent(context, AppLocalePickerActivity::class.java).apply {
data = Uri.parse("package:${record.app.packageName}")
this.putExtra("uid", record.app.uid)
}
context.startActivity(intent)
}
}
}

View File

@@ -156,13 +156,13 @@ class AllAppListTest {
private fun setItemContent() { private fun setItemContent() {
composeTestRule.setContent { composeTestRule.setContent {
AllAppListPage { fakeNavControllerWrapper.Wrapper {
fakeNavControllerWrapper.Wrapper { with(AllAppListModel()) {
AppListItemModel( AppListItemModel(
record = AppRecordWithSize(app = APP), record = AppRecordWithSize(app = APP),
label = LABEL, label = LABEL,
summary = stateOf(SUMMARY), summary = stateOf(SUMMARY),
).appItem() ).AppItem()
} }
} }
} }