diff options
| author | 2025-02-07 18:42:33 +0000 | |
|---|---|---|
| committer | 2025-02-07 19:28:44 +0000 | |
| commit | e84628f962fcd647761fb6ccc952d54b06c87adc (patch) | |
| tree | 60fd43da498e8b9994fb6bebd8195ba31d22f646 | |
| parent | fe0c403451993e8e9bf0a272074bc96da5724819 (diff) | |
[SB][Chips] Squish 2 chips even when ChipsModernization is on.
Ideally we could do this in Compose and do it smartly (e.g. if we can fit the
first chip with text and the second chip as icon-only we should do that), but
given our time constraints, let's not worry about doing it in Compose for now.
Bug: 392895330
Bug: 364653005
Change-Id: I8bf6563876dcb9b49a7a99b874e72bf810c92963
Flag: com.android.systemui.status_bar_notification_chips
Test: enable chips_modernization and then trigger 2 timer chips (e.g. call &
screen record) -> verify both chips show and show as icon only
Change-Id: I862c7efa3667df18b150b6d3bf7619297c5a292a
2 files changed, 146 insertions, 17 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt index 403ac3288128..20637cd4af33 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsWithNotifsViewModelTest.kt @@ -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]) diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt index 3ba0ae3b3cb6..1a30caf0150b 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/chips/ui/viewmodel/OngoingActivityChipsViewModel.kt @@ -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() |