diff options
| author | 2022-11-16 02:16:50 +0000 | |
|---|---|---|
| committer | 2022-11-16 02:16:50 +0000 | |
| commit | c0d2dfe2d659af39f90d03a118ba3de3272bc148 (patch) | |
| tree | ac9a430b70e69a88762387da87d74a443c507e6f | |
| parent | 027397129047edbd330f5fc49f0d53261c6b452a (diff) | |
| parent | a907c9d949f406fe5e69e5c3f6b491dad003b476 (diff) | |
Merge "Support grouping in the New App List"
3 files changed, 74 insertions, 13 deletions
diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt index 373b57f73ef0..a7122d0eb03a 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/model/app/AppListModel.kt @@ -54,6 +54,14 @@ interface AppListModel<T : AppRecord> { ) /** + * Gets the group title of this item. + * + * Note: Items should be sorted by group in [getComparator] first, this [getGroupTitle] will not + * change the list order. + */ + fun getGroupTitle(option: Int, record: T): String? = null + + /** * Gets the summary for the given app record. * * @return null if no summary should be displayed. diff --git a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt index 7f5fe9f75d51..681eb1c3508e 100644 --- a/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt +++ b/packages/SettingsLib/SpaPrivileged/src/com/android/settingslib/spaprivileged/template/app/AppList.kt @@ -34,9 +34,11 @@ import com.android.settingslib.spa.framework.compose.LogCompositions import com.android.settingslib.spa.framework.compose.TimeMeasurer.Companion.rememberTimeMeasurer import com.android.settingslib.spa.framework.compose.rememberLazyListStateAndHideKeyboardWhenStartScroll import com.android.settingslib.spa.framework.compose.toState +import com.android.settingslib.spa.widget.ui.CategoryTitle import com.android.settingslib.spa.widget.ui.PlaceholderTitle import com.android.settingslib.spaprivileged.R import com.android.settingslib.spaprivileged.framework.compose.DisposableBroadcastReceiverAsUser +import com.android.settingslib.spaprivileged.model.app.AppEntry import com.android.settingslib.spaprivileged.model.app.AppListConfig import com.android.settingslib.spaprivileged.model.app.AppListData import com.android.settingslib.spaprivileged.model.app.AppListModel @@ -100,17 +102,28 @@ private fun <T : AppRecord> AppListWidget( } items(count = list.size, key = { option to list[it].record.app.packageName }) { + remember(list) { listModel.getGroupTitleIfFirst(option, list, it) } + ?.let { group -> CategoryTitle(title = group) } + val appEntry = list[it] val summary = listModel.getSummary(option, appEntry.record) ?: "".toState() - val itemModel = remember(appEntry) { + appItem(remember(appEntry) { AppListItemModel(appEntry.record, appEntry.label, summary) - } - appItem(itemModel) + }) } } } } +/** Returns group title if this is the first item of the group. */ +private fun <T : AppRecord> AppListModel<T>.getGroupTitleIfFirst( + option: Int, + list: List<AppEntry<T>>, + index: Int, +): String? = getGroupTitle(option, list[index].record)?.takeIf { + index == 0 || it != getGroupTitle(option, list[index - 1].record) +} + @Composable private fun <T : AppRecord> loadAppListData( config: AppListConfig, diff --git a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt index 80c4eac9b98f..9f20c78485a8 100644 --- a/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt +++ b/packages/SettingsLib/SpaPrivileged/tests/src/com/android/settingslib/spaprivileged/template/app/AppListTest.kt @@ -58,26 +58,43 @@ class AppListTest { @Test fun couldShowAppItem() { - setContent(appEntries = listOf(APP_ENTRY)) + setContent(appEntries = listOf(APP_ENTRY_A)) - composeTestRule.onNodeWithText(APP_ENTRY.label).assertIsDisplayed() + composeTestRule.onNodeWithText(APP_ENTRY_A.label).assertIsDisplayed() } @Test fun couldShowHeader() { - setContent(header = { Text(HEADER) }, appEntries = listOf(APP_ENTRY)) + setContent(appEntries = listOf(APP_ENTRY_A), header = { Text(HEADER) }) composeTestRule.onNodeWithText(HEADER).assertIsDisplayed() } + @Test + fun whenNotGrouped_groupTitleDoesNotExist() { + setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = false) + + composeTestRule.onNodeWithText(GROUP_A).assertDoesNotExist() + composeTestRule.onNodeWithText(GROUP_B).assertDoesNotExist() + } + + @Test + fun whenGrouped_groupTitleDisplayed() { + setContent(appEntries = listOf(APP_ENTRY_A, APP_ENTRY_B), enableGrouping = true) + + composeTestRule.onNodeWithText(GROUP_A).assertIsDisplayed() + composeTestRule.onNodeWithText(GROUP_B).assertIsDisplayed() + } + private fun setContent( - header: @Composable () -> Unit = {}, appEntries: List<AppEntry<TestAppRecord>>, + header: @Composable () -> Unit = {}, + enableGrouping: Boolean = false, ) { composeTestRule.setContent { AppList( config = AppListConfig(userId = USER_ID, showInstantApps = false), - listModel = TestAppListModel(), + listModel = TestAppListModel(enableGrouping), state = AppListState( showSystem = false.toState(), option = 0.toState(), @@ -96,17 +113,37 @@ class AppListTest { private companion object { const val USER_ID = 0 const val HEADER = "Header" - val APP_ENTRY = AppEntry( - record = TestAppRecord(ApplicationInfo()), - label = "AAA", + const val GROUP_A = "Group A" + const val GROUP_B = "Group B" + val APP_ENTRY_A = AppEntry( + record = TestAppRecord( + app = ApplicationInfo().apply { + packageName = "package.name.a" + }, + group = GROUP_A, + ), + label = "Label A", + labelCollationKey = CollationKey("", byteArrayOf()), + ) + val APP_ENTRY_B = AppEntry( + record = TestAppRecord( + app = ApplicationInfo().apply { + packageName = "package.name.b" + }, + group = GROUP_B, + ), + label = "Label B", labelCollationKey = CollationKey("", byteArrayOf()), ) } } -private data class TestAppRecord(override val app: ApplicationInfo) : AppRecord +private data class TestAppRecord( + override val app: ApplicationInfo, + val group: String? = null, +) : AppRecord -private class TestAppListModel : AppListModel<TestAppRecord> { +private class TestAppListModel(val enableGrouping: Boolean) : AppListModel<TestAppRecord> { override fun transform(userIdFlow: Flow<Int>, appListFlow: Flow<List<ApplicationInfo>>) = appListFlow.asyncMapItem { TestAppRecord(it) } @@ -118,4 +155,7 @@ private class TestAppListModel : AppListModel<TestAppRecord> { option: Int, recordListFlow: Flow<List<TestAppRecord>>, ) = recordListFlow + + override fun getGroupTitle(option: Int, record: TestAppRecord) = + if (enableGrouping) record.group else null } |