Merge "Fix the selected option not saved for App List"

This commit is contained in:
Chaohui Wang
2023-01-17 11:35:28 +00:00
committed by Android (Google) Code Review
4 changed files with 17 additions and 15 deletions

View File

@@ -51,7 +51,7 @@ internal data class AppListData<T : AppRecord>(
}
internal interface IAppListViewModel<T : AppRecord> {
val option: StateFlowBridge<Int?>
val optionFlow: MutableStateFlow<Int?>
val spinnerOptionsFlow: Flow<List<SpinnerOption>>
val appListDataFlow: Flow<AppListData<T>>
}
@@ -69,7 +69,7 @@ internal open class AppListViewModelImpl<T : AppRecord>(
val appListConfig = StateFlowBridge<AppListConfig>()
val listModel = StateFlowBridge<AppListModel<T>>()
val showSystem = StateFlowBridge<Boolean>()
final override val option = StateFlowBridge<Int?>()
final override val optionFlow = MutableStateFlow<Int?>(null)
val searchQuery = StateFlowBridge<String>()
private val appListRepository = appListRepositoryFactory(application)
@@ -97,7 +97,7 @@ internal open class AppListViewModelImpl<T : AppRecord>(
listModel.getSpinnerOptions(recordList)
}
override val appListDataFlow = option.flow.flatMapLatest(::filterAndSort)
override val appListDataFlow = optionFlow.filterNotNull().flatMapLatest(::filterAndSort)
.combine(searchQuery.flow) { appListData, searchQuery ->
appListData.filter {
it.label.contains(other = searchQuery, ignoreCase = true)

View File

@@ -24,11 +24,10 @@ import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.Dp
@@ -37,7 +36,6 @@ 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.framework.util.StateFlowBridge
import com.android.settingslib.spa.widget.ui.CategoryTitle
import com.android.settingslib.spa.widget.ui.PlaceholderTitle
import com.android.settingslib.spa.widget.ui.Spinner
@@ -52,6 +50,7 @@ import com.android.settingslib.spaprivileged.model.app.AppListViewModel
import com.android.settingslib.spaprivileged.model.app.AppRecord
import com.android.settingslib.spaprivileged.model.app.IAppListViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
private const val TAG = "AppList"
private const val CONTENT_TYPE_HEADER = "header"
@@ -88,7 +87,7 @@ internal fun <T : AppRecord> AppListInput<T>.AppListImpl(
val viewModel = viewModelSupplier()
Column(Modifier.fillMaxSize()) {
val optionsState = viewModel.spinnerOptionsFlow.collectAsState(null, Dispatchers.IO)
SpinnerOptions(optionsState, viewModel.option)
SpinnerOptions(optionsState, viewModel.optionFlow)
val appListData = viewModel.appListDataFlow.collectAsState(null, Dispatchers.IO)
listModel.AppListWidget(appListData, header, bottomPadding, noItemMessage)
}
@@ -97,15 +96,18 @@ internal fun <T : AppRecord> AppListInput<T>.AppListImpl(
@Composable
private fun SpinnerOptions(
optionsState: State<List<SpinnerOption>?>,
optionBridge: StateFlowBridge<Int?>,
optionFlow: MutableStateFlow<Int?>,
) {
val options = optionsState.value
val selectedOption = rememberSaveable(options) {
mutableStateOf(options?.let { it.firstOrNull()?.id ?: -1 })
LaunchedEffect(options) {
if (options != null && !options.any { it.id == optionFlow.value }) {
// Reset to first option if the available options changed, and the current selected one
// does not in the new options.
optionFlow.value = options.let { it.firstOrNull()?.id ?: -1 }
}
}
optionBridge.Sync(selectedOption)
if (options != null) {
Spinner(options, selectedOption.value) { selectedOption.value = it }
Spinner(options, optionFlow.collectAsState().value) { optionFlow.value = it }
}
}

View File

@@ -56,7 +56,7 @@ class AppListViewModelTest {
viewModel.appListConfig.setIfAbsent(CONFIG)
viewModel.listModel.setIfAbsent(listModel)
viewModel.showSystem.setIfAbsent(false)
viewModel.option.setIfAbsent(0)
viewModel.optionFlow.value = 0
viewModel.searchQuery.setIfAbsent("")
viewModel.reloadApps()
return viewModel

View File

@@ -29,7 +29,6 @@ import androidx.compose.ui.unit.dp
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settingslib.spa.framework.compose.toState
import com.android.settingslib.spa.framework.util.StateFlowBridge
import com.android.settingslib.spa.widget.ui.SpinnerOption
import com.android.settingslib.spaprivileged.R
import com.android.settingslib.spaprivileged.model.app.AppEntry
@@ -38,6 +37,7 @@ import com.android.settingslib.spaprivileged.model.app.AppListData
import com.android.settingslib.spaprivileged.model.app.IAppListViewModel
import com.android.settingslib.spaprivileged.tests.testutils.TestAppListModel
import com.android.settingslib.spaprivileged.tests.testutils.TestAppRecord
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import org.junit.Rule
import org.junit.Test
@@ -125,7 +125,7 @@ class AppListTest {
bottomPadding = 0.dp,
).AppListImpl {
object : IAppListViewModel<TestAppRecord> {
override val option: StateFlowBridge<Int?> = StateFlowBridge()
override val optionFlow: MutableStateFlow<Int?> = MutableStateFlow(null)
override val spinnerOptionsFlow = flowOf(options.mapIndexed { index, option ->
SpinnerOption(id = index, text = option)
})