Merge "Support grouping in the New App List"
This commit is contained in:
@@ -53,6 +53,14 @@ interface AppListModel<T : AppRecord> {
|
||||
{ it.record.app.uid },
|
||||
)
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user