Merge "Add spinner options to "All apps""
This commit is contained in:
@@ -16,10 +16,12 @@
|
||||
|
||||
package com.android.settings.spa.app
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.os.Bundle
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import com.android.settings.R
|
||||
@@ -28,9 +30,12 @@ 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.rememberContext
|
||||
import com.android.settingslib.spa.framework.util.filterItem
|
||||
import com.android.settingslib.spa.framework.util.mapItem
|
||||
import com.android.settingslib.spa.widget.preference.Preference
|
||||
import com.android.settingslib.spa.widget.preference.PreferenceModel
|
||||
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
import com.android.settingslib.spaprivileged.template.app.AppList
|
||||
@@ -67,7 +72,7 @@ fun AllAppListPage(
|
||||
val resetAppDialogPresenter = rememberResetAppDialogPresenter()
|
||||
AppListPage(
|
||||
title = stringResource(R.string.all_apps),
|
||||
listModel = remember { AllAppListModel() },
|
||||
listModel = rememberContext(::AllAppListModel),
|
||||
showInstantApps = true,
|
||||
moreOptions = { ResetAppPreferences(resetAppDialogPresenter::open) },
|
||||
appList = appList,
|
||||
@@ -79,17 +84,71 @@ data class AppRecordWithSize(
|
||||
) : AppRecord
|
||||
|
||||
class AllAppListModel(
|
||||
private val getSummary: @Composable ApplicationInfo.() -> State<String> = { getStorageSize() },
|
||||
private val context: Context,
|
||||
private val getStorageSummary: @Composable ApplicationInfo.() -> State<String> = {
|
||||
getStorageSize()
|
||||
},
|
||||
) : AppListModel<AppRecordWithSize> {
|
||||
|
||||
override fun getSpinnerOptions(recordList: List<AppRecordWithSize>): List<SpinnerOption> {
|
||||
val hasDisabled = recordList.any(isDisabled)
|
||||
val hasInstant = recordList.any(isInstant)
|
||||
if (!hasDisabled && !hasInstant) return emptyList()
|
||||
val options = mutableListOf(SpinnerItem.All, SpinnerItem.Enabled)
|
||||
if (hasDisabled) options += SpinnerItem.Disabled
|
||||
if (hasInstant) options += SpinnerItem.Instant
|
||||
return options.map {
|
||||
SpinnerOption(
|
||||
id = it.ordinal,
|
||||
text = context.getString(it.stringResId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) =
|
||||
appListFlow.mapItem(::AppRecordWithSize)
|
||||
|
||||
override fun filter(
|
||||
userIdFlow: Flow<Int>,
|
||||
option: Int,
|
||||
recordListFlow: Flow<List<AppRecordWithSize>>,
|
||||
): Flow<List<AppRecordWithSize>> = recordListFlow.filterItem(
|
||||
when (SpinnerItem.values().getOrNull(option)) {
|
||||
SpinnerItem.Enabled -> ({ it.app.enabled && !it.app.isInstantApp })
|
||||
SpinnerItem.Disabled -> isDisabled
|
||||
SpinnerItem.Instant -> isInstant
|
||||
else -> ({ true })
|
||||
}
|
||||
)
|
||||
|
||||
private val isDisabled: (AppRecordWithSize) -> Boolean =
|
||||
{ !it.app.enabled && !it.app.isInstantApp }
|
||||
|
||||
private val isInstant: (AppRecordWithSize) -> Boolean = { it.app.isInstantApp }
|
||||
|
||||
@Composable
|
||||
override fun getSummary(option: Int, record: AppRecordWithSize) = record.app.getSummary()
|
||||
override fun getSummary(option: Int, record: AppRecordWithSize): State<String> {
|
||||
val storageSummary = record.app.getStorageSummary()
|
||||
return remember {
|
||||
derivedStateOf {
|
||||
storageSummary.value +
|
||||
when (isDisabled(record)) {
|
||||
true -> System.lineSeparator() + context.getString(R.string.disabled)
|
||||
else -> ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun AppListItemModel<AppRecordWithSize>.AppItem() {
|
||||
AppListItem(onClick = AppInfoSettingsProvider.navigator(app = record.app))
|
||||
}
|
||||
}
|
||||
|
||||
private enum class SpinnerItem(val stringResId: Int) {
|
||||
All(R.string.filter_all_apps),
|
||||
Enabled(R.string.filter_enabled_apps),
|
||||
Disabled(R.string.filter_apps_disabled),
|
||||
Instant(R.string.filter_instant_apps);
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ import androidx.compose.runtime.State
|
||||
import com.android.settings.R
|
||||
import com.android.settings.spa.development.UsageStatsListModel.SpinnerItem.Companion.toSpinnerItem
|
||||
import com.android.settingslib.spa.framework.compose.stateOf
|
||||
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
||||
import com.android.settingslib.spaprivileged.model.app.AppEntry
|
||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
@@ -53,9 +54,13 @@ class UsageStatsListModel(private val context: Context) : AppListModel<UsageStat
|
||||
appList.map { app -> UsageStatsAppRecord(app, usageStatsMap[app.packageName]) }
|
||||
}
|
||||
|
||||
override fun getSpinnerOptions() = SpinnerItem.values().map {
|
||||
context.getString(it.stringResId)
|
||||
}
|
||||
override fun getSpinnerOptions(recordList: List<UsageStatsAppRecord>): List<SpinnerOption> =
|
||||
SpinnerItem.values().map {
|
||||
SpinnerOption(
|
||||
id = it.ordinal,
|
||||
text = context.getString(it.stringResId),
|
||||
)
|
||||
}
|
||||
|
||||
override fun filter(
|
||||
userIdFlow: Flow<Int>,
|
||||
@@ -75,7 +80,8 @@ class UsageStatsListModel(private val context: Context) : AppListModel<UsageStat
|
||||
override fun getSummary(option: Int, record: UsageStatsAppRecord): State<String>? {
|
||||
val usageStats = record.usageStats ?: return null
|
||||
val lastTimeUsed = DateUtils.formatSameDayTime(
|
||||
usageStats.lastTimeUsed, now, DateFormat.MEDIUM, DateFormat.MEDIUM)
|
||||
usageStats.lastTimeUsed, now, DateFormat.MEDIUM, DateFormat.MEDIUM
|
||||
)
|
||||
val lastTimeUsedLine = "${context.getString(R.string.last_time_used_label)}: $lastTimeUsed"
|
||||
val usageTime = DateUtils.formatElapsedTime(usageStats.totalTimeInForeground / 1000)
|
||||
val usageTimeLine = "${context.getString(R.string.usage_time_label)}: $usageTime"
|
||||
|
@@ -30,6 +30,7 @@ import com.android.settings.spa.notification.SpinnerItem.Companion.toSpinnerItem
|
||||
import com.android.settingslib.spa.framework.compose.stateOf
|
||||
import com.android.settingslib.spa.framework.util.asyncFilter
|
||||
import com.android.settingslib.spa.framework.util.asyncForEach
|
||||
import com.android.settingslib.spa.widget.ui.SpinnerOption
|
||||
import com.android.settingslib.spaprivileged.model.app.AppEntry
|
||||
import com.android.settingslib.spaprivileged.model.app.AppListModel
|
||||
import com.android.settingslib.spaprivileged.model.app.AppRecord
|
||||
@@ -78,8 +79,9 @@ class AppNotificationsListModel(
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun onFirstLoaded(recordList: List<AppNotificationsRecord>) {
|
||||
override suspend fun onFirstLoaded(recordList: List<AppNotificationsRecord>): Boolean {
|
||||
recordList.asyncForEach { it.controller.getEnabled() }
|
||||
return true
|
||||
}
|
||||
|
||||
override fun getComparator(option: Int) = when (option.toSpinnerItem()) {
|
||||
@@ -97,9 +99,13 @@ class AppNotificationsListModel(
|
||||
}
|
||||
}
|
||||
|
||||
override fun getSpinnerOptions() = SpinnerItem.values().map {
|
||||
context.getString(it.stringResId)
|
||||
}
|
||||
override fun getSpinnerOptions(recordList: List<AppNotificationsRecord>): List<SpinnerOption> =
|
||||
SpinnerItem.values().map {
|
||||
SpinnerOption(
|
||||
id = it.ordinal,
|
||||
text = context.getString(it.stringResId),
|
||||
)
|
||||
}
|
||||
|
||||
private fun formatLastSent(lastSent: Long) =
|
||||
StringUtil.formatRelativeTime(
|
||||
|
@@ -121,7 +121,7 @@ class AllAppListTest {
|
||||
@OptIn(ExperimentalCoroutinesApi::class)
|
||||
@Test
|
||||
fun allAppListModel_transform() = runTest {
|
||||
val listModel = AllAppListModel { stateOf(SUMMARY) }
|
||||
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
||||
|
||||
val recordListFlow = listModel.transform(flowOf(USER_ID), flowOf(listOf(APP)))
|
||||
|
||||
@@ -132,7 +132,7 @@ class AllAppListTest {
|
||||
|
||||
@Test
|
||||
fun allAppListModel_getSummary() {
|
||||
val listModel = AllAppListModel { stateOf(SUMMARY) }
|
||||
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
||||
|
||||
lateinit var summaryState: State<String>
|
||||
composeTestRule.setContent {
|
||||
@@ -142,6 +142,23 @@ class AllAppListTest {
|
||||
assertThat(summaryState.value).isEqualTo(SUMMARY)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun allAppListModel_getSummaryWhenDisabled() {
|
||||
val listModel = AllAppListModel(context) { stateOf(SUMMARY) }
|
||||
val disabledApp = ApplicationInfo().apply {
|
||||
packageName = PACKAGE_NAME
|
||||
enabled = false
|
||||
}
|
||||
|
||||
lateinit var summaryState: State<String>
|
||||
composeTestRule.setContent {
|
||||
summaryState =
|
||||
listModel.getSummary(option = 0, record = AppRecordWithSize(app = disabledApp))
|
||||
}
|
||||
|
||||
assertThat(summaryState.value).isEqualTo("$SUMMARY${System.lineSeparator()}Disabled")
|
||||
}
|
||||
|
||||
private fun getAppListInput(): AppListInput<AppRecordWithSize> {
|
||||
lateinit var input: AppListInput<AppRecordWithSize>
|
||||
composeTestRule.setContent {
|
||||
@@ -157,7 +174,7 @@ class AllAppListTest {
|
||||
private fun setItemContent() {
|
||||
composeTestRule.setContent {
|
||||
fakeNavControllerWrapper.Wrapper {
|
||||
with(AllAppListModel()) {
|
||||
with(AllAppListModel(context)) {
|
||||
AppListItemModel(
|
||||
record = AppRecordWithSize(app = APP),
|
||||
label = LABEL,
|
||||
|
Reference in New Issue
Block a user