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

Commit cc000eac authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[SB][Chips] Squish 2 chips even when ChipsModernization is on." into main

parents 08369522 e84628f9
Loading
Loading
Loading
Loading
+95 −4
Original line number Diff line number Diff line
@@ -293,7 +293,7 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {

    @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chipsLegacy_twoTimerChips_isSmallPortrait_andChipsModernizationDisabled_bothSquished() =
    fun chipsLegacy_twoTimerChips_isSmallPortrait_bothSquished() =
        kosmos.runTest {
            screenRecordState.value = ScreenRecordModel.Recording
            addOngoingCallState(key = "call")
@@ -307,6 +307,22 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
        }

    @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chips_twoTimerChips_isSmallPortrait_bothSquished() =
        kosmos.runTest {
            screenRecordState.value = ScreenRecordModel.Recording
            addOngoingCallState(key = "call")

            val latest by collectLastValue(underTest.chips)

            // Squished chips are icon only
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
            assertThat(latest!!.active[1])
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
        }

    @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chipsLegacy_countdownChipAndTimerChip_countdownNotSquished_butTimerSquished() =
@@ -324,6 +340,23 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
        }

    @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chips_countdownChipAndTimerChip_countdownNotSquished_butTimerSquished() =
        kosmos.runTest {
            screenRecordState.value = ScreenRecordModel.Starting(millisUntilStarted = 2000)
            addOngoingCallState(key = "call")

            val latest by collectLastValue(underTest.chips)

            // The screen record countdown isn't squished to icon-only
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.Countdown::class.java)
            // But the call chip *is* squished
            assertThat(latest!!.active[1])
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
        }

    @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chipsLegacy_numberOfChipsChanges_chipsGetSquishedAndUnsquished() =
@@ -360,6 +393,38 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                .isInstanceOf(OngoingActivityChipModel.Inactive::class.java)
        }

    @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chips_numberOfChipsChanges_chipsGetSquishedAndUnsquished() =
        kosmos.runTest {
            val latest by collectLastValue(underTest.chips)

            // WHEN there's only one chip
            screenRecordState.value = ScreenRecordModel.Recording
            removeOngoingCallState(key = "call")

            // The screen record isn't squished because it's the only one
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)

            // WHEN there's 2 chips
            addOngoingCallState(key = "call")

            // THEN they both become squished
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)
            // But the call chip *is* squished
            assertThat(latest!!.active[1])
                .isInstanceOf(OngoingActivityChipModel.Active.IconOnly::class.java)

            // WHEN we go back down to 1 chip
            screenRecordState.value = ScreenRecordModel.DoingNothing

            // THEN the remaining chip unsquishes
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
        }

    @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chipsLegacy_twoChips_isLandscape_notSquished() =
@@ -383,6 +448,29 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
        }

    @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chips_twoChips_isLandscape_notSquished() =
        kosmos.runTest {
            screenRecordState.value = ScreenRecordModel.Recording
            addOngoingCallState(key = "call")

            // WHEN we're in landscape
            val config =
                Configuration(kosmos.mainResources.configuration).apply {
                    orientation = Configuration.ORIENTATION_LANDSCAPE
                }
            kosmos.fakeConfigurationRepository.onConfigurationChange(config)

            val latest by collectLastValue(underTest.chips)

            // THEN the chips aren't squished (squished chips would be icon only)
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
            assertThat(latest!!.active[1])
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
        }

    @DisableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    @Test
    fun chipsLegacy_twoChips_isLargeScreen_notSquished() =
@@ -402,16 +490,19 @@ class OngoingActivityChipsWithNotifsViewModelTest : SysuiTestCase() {
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
        }

    @Test
    @EnableFlags(StatusBarChipsModernization.FLAG_NAME, StatusBarRootModernization.FLAG_NAME)
    fun chips_twoChips_chipsModernizationEnabled_notSquished() =
    @Test
    fun chips_twoChips_isLargeScreen_notSquished() =
        kosmos.runTest {
            screenRecordState.value = ScreenRecordModel.Recording
            addOngoingCallState(key = "call")

            // WHEN we're on a large screen
            kosmos.displayStateRepository.setIsLargeScreen(true)

            val latest by collectLastValue(underTest.chips)

            // Squished chips would be icon only
            // THEN the chips aren't squished (squished chips would be icon only)
            assertThat(latest!!.active[0])
                .isInstanceOf(OngoingActivityChipModel.Active.Timer::class.java)
            assertThat(latest!!.active[1])
+51 −13
Original line number Diff line number Diff line
@@ -214,7 +214,6 @@ constructor(
                    if (
                        secondaryChip is InternalChipModel.Active &&
                            StatusBarNotifChips.isEnabled &&
                            !StatusBarChipsModernization.isEnabled &&
                            !isScreenReasonablyLarge
                    ) {
                        // If we have two showing chips and we don't have a ton of room
@@ -222,8 +221,10 @@ constructor(
                        // possible so that we have the highest chance of showing both chips (as
                        // opposed to showing the primary chip with a lot of text and completely
                        // hiding the secondary chip).
                        // Also: If StatusBarChipsModernization is enabled, then we'll do the
                        // squishing in Compose instead.
                        // TODO(b/392895330): If StatusBarChipsModernization is enabled, do the
                        // squishing in Compose instead, and be smart about it (e.g. if we have
                        // room for the first chip to show text and the second chip to be icon-only,
                        // do that instead of always squishing both chips.)
                        InternalMultipleOngoingActivityChipsModel(
                            primaryChip.squish(),
                            secondaryChip.squish(),
@@ -237,24 +238,31 @@ constructor(

    /** Squishes the chip down to the smallest content possible. */
    private fun InternalChipModel.Active.squish(): InternalChipModel.Active {
        return when (model) {
        return if (model.shouldSquish()) {
            InternalChipModel.Active(this.type, this.model.toIconOnly())
        } else {
            this
        }
    }

    private fun OngoingActivityChipModel.Active.shouldSquish(): Boolean {
        return when (this) {
            // Icon-only is already maximum squished
            is OngoingActivityChipModel.Active.IconOnly -> this
            is OngoingActivityChipModel.Active.IconOnly,
            // Countdown shows just a single digit, so already maximum squished
            is OngoingActivityChipModel.Active.Countdown -> this
            // The other chips have icon+text, so we should hide the text
            is OngoingActivityChipModel.Active.Countdown -> false
            // The other chips have icon+text, so we can squish them by hiding text
            is OngoingActivityChipModel.Active.Timer,
            is OngoingActivityChipModel.Active.ShortTimeDelta,
            is OngoingActivityChipModel.Active.Text ->
                InternalChipModel.Active(this.type, this.model.toIconOnly())
            is OngoingActivityChipModel.Active.Text -> true
        }
    }

    private fun OngoingActivityChipModel.Active.toIconOnly(): OngoingActivityChipModel.Active {
        // If this chip doesn't have an icon, then it only has text and we should continue showing
        // its text. (This is theoretically impossible because
        // [OngoingActivityChipModel.Active.Countdown] is the only chip without an icon, but protect
        // against it just in case.)
        // [OngoingActivityChipModel.Active.Countdown] is the only chip without an icon and
        // [shouldSquish] returns false for that model, but protect against it just in case.)
        val currentIcon = icon ?: return this
        return OngoingActivityChipModel.Active.IconOnly(
            key,
@@ -271,8 +279,38 @@ constructor(
     */
    val chips: StateFlow<MultipleOngoingActivityChipsModel> =
        if (StatusBarChipsModernization.isEnabled) {
            incomingChipBundle
                .map { bundle -> rankChips(bundle) }
            combine(
                    incomingChipBundle.map { bundle -> rankChips(bundle) },
                    isScreenReasonablyLarge,
                ) { rankedChips, isScreenReasonablyLarge ->
                    if (
                        StatusBarNotifChips.isEnabled &&
                            !isScreenReasonablyLarge &&
                            rankedChips.active.filter { !it.isHidden }.size >= 2
                    ) {
                        // If we have at least two showing chips and we don't have a ton of room
                        // (!isScreenReasonablyLarge), then we want to make both of them as small as
                        // possible so that we have the highest chance of showing both chips (as
                        // opposed to showing the first chip with a lot of text and completely
                        // hiding the other chips).
                        val squishedActiveChips =
                            rankedChips.active.map {
                                if (!it.isHidden && it.shouldSquish()) {
                                    it.toIconOnly()
                                } else {
                                    it
                                }
                            }

                        MultipleOngoingActivityChipsModel(
                            active = squishedActiveChips,
                            overflow = rankedChips.overflow,
                            inactive = rankedChips.inactive,
                        )
                    } else {
                        rankedChips
                    }
                }
                .stateIn(scope, SharingStarted.Lazily, MultipleOngoingActivityChipsModel())
        } else {
            MutableStateFlow(MultipleOngoingActivityChipsModel()).asStateFlow()