Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ff202e7f authored by Santiago Etchebehere's avatar Santiago Etchebehere
Browse files

Improve support for no shape options

Remove the container view completely if no options are available.
Make sure "themedIconsAvailable" is properly read the first time.

Bug: 415116909
Flag: com.android.systemui.shared.new_customization_picker_ui
Test: added tests and manually verified
Change-Id: If50d0dd2ee50f909730501e8f02f4db6e6f122c5
parent 2553c12e
Loading
Loading
Loading
Loading
+2 −5
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.callbackFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.shareIn
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

@@ -95,11 +96,7 @@ constructor(

    override val isAvailable: Flow<Boolean> =
        uri.map { it != null }
            .stateIn(
                scope = backgroundScope,
                started = SharingStarted.WhileSubscribed(),
                initialValue = false,
            )
            .shareIn(scope = backgroundScope, started = SharingStarted.WhileSubscribed())

    override val isActivated: Flow<Boolean> =
        callbackFlow {
+14 −8
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ object AppIconFloatingSheetBinder {
            shouldAnimate = isFloatingSheetActive,
            lifecycleOwner = lifecycleOwner,
        )
        val shapeSection = view.requireViewById<View>(R.id.app_shape_container)

        val shapeOptionListAdapter =
            createShapeOptionItemAdapter(
@@ -85,14 +86,19 @@ object AppIconFloatingSheetBinder {
        lifecycleOwner.lifecycleScope.launch {
            lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                launch {
                    viewModel.isShapeOptionsAvailable.collect { shapeAvailable ->
                        shapeSection.isVisible = shapeAvailable
                        if (shapeAvailable) {
                            viewModel.shapeOptions.collect { options ->
                        shapeOptionList.isVisible = options.size > 1
                                shapeOptionListAdapter.setItems(options) {
                                    val indexToFocus =
                                options.indexOfFirst { it.isSelected.value }.coerceAtLeast(0)
                            (shapeOptionList.layoutManager as LinearLayoutManager).scrollToPosition(
                                indexToFocus
                            )
                                        options
                                            .indexOfFirst { it.isSelected.value }
                                            .coerceAtLeast(0)
                                    (shapeOptionList.layoutManager as LinearLayoutManager)
                                        .scrollToPosition(indexToFocus)
                                }
                            }
                        }
                    }
                }
+9 −3
Original line number Diff line number Diff line
@@ -73,12 +73,14 @@ constructor(
            .map { shapeOptions -> shapeOptions.map { toShapeOptionItemViewModel(it) } }
            .shareIn(scope = viewModelScope, started = SharingStarted.Lazily, replay = 1)

    val isShapeOptionsAvailable: Flow<Boolean> = shapeOptions.map { it.size > 1 }

    //// Themed icons enabled
    val isThemedIconAvailable =
        interactor.isThemedIconAvailable.shareIn(
            scope = viewModelScope,
            started = SharingStarted.Lazily,
            replay = 1,
            replay = 0,
        )

    private val overridingIsThemedIconEnabled = MutableStateFlow<Boolean?>(null)
@@ -103,8 +105,12 @@ constructor(
        }

    val summary: Flow<AppIconPickerSummaryViewModel> =
        combine(selectedShape, isThemedIconEnabled) { selectedShape, isThemedIconEnabled ->
            val selectedShapeString = selectedShape.text.asString(applicationContext)
        combine(selectedShape, isThemedIconEnabled, isShapeOptionsAvailable) {
            selectedShape,
            isThemedIconEnabled,
            isShapeOptionsAvailable ->
            val selectedShapeString =
                if (isShapeOptionsAvailable) selectedShape.text.asString(applicationContext) else ""
            val appIconThemeString =
                if (isThemedIconEnabled) {
                    applicationContext.getString(R.string.app_icons_theme_themed)
+3 −3
Original line number Diff line number Diff line
@@ -78,12 +78,12 @@ constructor(
        combine(
            gridPickerViewModel.isGridCustomizationAvailable,
            appIconPickerViewModel.isThemedIconAvailable,
            appIconPickerViewModel.shapeOptions,
        ) { isGridCustomizationAvailable, isThemedIconAvailable, shapeOptions ->
            appIconPickerViewModel.isShapeOptionsAvailable,
        ) { isGridCustomizationAvailable, isThemedIconAvailable, isShapeOptionsAvailable ->
            ThemePickerCustomizationOptionsData(
                isGridCustomizationAvailable = isGridCustomizationAvailable,
                isThemedIconAvailable = isThemedIconAvailable,
                isShapeAvailable = shapeOptions.size > 1,
                isShapeAvailable = isShapeOptionsAvailable,
            )
        }

+29 −0
Original line number Diff line number Diff line
@@ -316,6 +316,35 @@ class AppIconPickerViewModelTest {
        }
    }

    @Test
    fun summary_shouldOnlyShowTheme_ifOnlyOneShape() {
        testScope.runTest {
            shapeManager.setShapeOptions(shapeManager.getShapeOptions().subList(0, 1))
            interactor.applyShape("")
            val summary = collectLastValue(underTest.summary)
            val currentSummary = summary()
            assertThat(currentSummary?.description?.asString(appContext)).doesNotMatch(".+,.+")
        }
    }

    @Test
    fun shapeOptionsAvailable_isTrueOnlyIfMoreThanOneOption() {
        testScope.runTest {
            val isAvailable = collectLastValue(underTest.isShapeOptionsAvailable)

            // setUp fills the shape options with DEFAULT_SHAPE_OPTION_LIST which has 5 items
            assertThat(isAvailable()).isEqualTo(true)

            shapeManager.setShapeOptions(shapeManager.getShapeOptions().subList(0, 1))
            interactor.applyShape("")
            assertThat(isAvailable()).isEqualTo(false)

            shapeManager.setShapeOptions(emptyList())
            interactor.applyShape("")
            assertThat(isAvailable()).isEqualTo(false)
        }
    }

    private fun TestScope.assertShapeItem(
        optionItem: OptionItemViewModel2<ShapeIconViewModel>?,
        key: String,