diff options
| author | 2024-09-26 10:10:24 -0700 | |
|---|---|---|
| committer | 2024-10-03 16:42:56 -0700 | |
| commit | ca2beefc51d2c7ca08a35d2b9e06a0ea008b44bc (patch) | |
| tree | 1b3bce0e7713a5490349e58440fc841b707011d6 | |
| parent | 04d09206b32f4faec39b8812bf204edfa5d2cb12 (diff) | |
[flexiglass] Fix HUN animation on Shade scene
Changes HunInteractor.pinnedHeadsUpRows to include both pinned states, so the view binder can generate animations for HUNs in shade (which are not considered to be pinned)
Bug: 369687582
Test: manually verified with logging that HUNs on Shade are not added to removelist
Test: manually verified HUNs animate in correctly on Shade
Flag: com.android.systemui.scene_container
Change-Id: I6e78a942a4d2e55737024a695a88020ea0f25823
5 files changed, 166 insertions, 24 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt index f40bfbdeb54b..8d678ef00b4a 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModelTest.kt @@ -506,7 +506,7 @@ class NotificationListViewModelTest(flags: FlagsParameterization) : SysuiTestCas @EnableSceneContainer fun pinnedHeadsUpRows_filtersForPinnedItems() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN there are no pinned rows val rows = diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt index aa203d7c0aa9..e25127e3e0d6 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractor.kt @@ -39,10 +39,10 @@ class HeadsUpNotificationInteractor @Inject constructor( private val headsUpRepository: HeadsUpRepository, - private val faceAuthInteractor: DeviceEntryFaceAuthInteractor, - private val keyguardTransitionInteractor: KeyguardTransitionInteractor, - private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor, - private val shadeInteractor: ShadeInteractor, + faceAuthInteractor: DeviceEntryFaceAuthInteractor, + keyguardTransitionInteractor: KeyguardTransitionInteractor, + notificationsKeyguardInteractor: NotificationsKeyguardInteractor, + shadeInteractor: ShadeInteractor, ) { /** The top-ranked heads up row, regardless of pinned state */ @@ -56,8 +56,7 @@ constructor( } .distinctUntilChanged() - /** Set of currently pinned top-level heads up rows to be displayed. */ - val pinnedHeadsUpRows: Flow<Set<HeadsUpRowKey>> by lazy { + private val activeHeadsUpRows: Flow<Set<Pair<HeadsUpRowKey, Boolean>>> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { flowOf(emptySet()) } else { @@ -67,9 +66,7 @@ constructor( repositories.map { repo -> repo.isPinned.map { isPinned -> repo to isPinned } } - combine(toCombine) { pairs -> - pairs.filter { (_, isPinned) -> isPinned }.map { (repo, _) -> repo }.toSet() - } + combine(toCombine) { pairs -> pairs.toSet() } } else { // if the set is empty, there are no flows to combine flowOf(emptySet()) @@ -78,6 +75,26 @@ constructor( } } + /** Set of currently active top-level heads up rows to be displayed. */ + val activeHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + activeHeadsUpRows.map { it.map { (repo, _) -> repo }.toSet() } + } + } + + /** Set of currently pinned top-level heads up rows to be displayed. */ + val pinnedHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + activeHeadsUpRows.map { + it.filter { (_, isPinned) -> isPinned }.map { (repo, _) -> repo }.toSet() + } + } + } + /** Are there any pinned heads up rows to display? */ val hasPinnedRows: Flow<Boolean> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt index 935e2a37b13c..38390e7bdb39 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewmodel/NotificationListViewModel.kt @@ -356,11 +356,23 @@ constructor( } } - val pinnedHeadsUpRows: Flow<Set<HeadsUpRowKey>> by lazy { + val activeHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { flowOf(emptySet()) } else { - headsUpNotificationInteractor.pinnedHeadsUpRows.dumpWhileCollecting("pinnedHeadsUpRows") + headsUpNotificationInteractor.activeHeadsUpRowKeys.dumpWhileCollecting( + "pinnedHeadsUpRows" + ) + } + } + + val pinnedHeadsUpRowKeys: Flow<Set<HeadsUpRowKey>> by lazy { + if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) { + flowOf(emptySet()) + } else { + headsUpNotificationInteractor.pinnedHeadsUpRowKeys.dumpWhileCollecting( + "pinnedHeadsUpRows" + ) } } diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt index dc15970b318b..e2e5c5970ff5 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt +++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ui/viewbinder/HeadsUpNotificationViewBinder.kt @@ -26,6 +26,7 @@ import javax.inject.Inject import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.launch class HeadsUpNotificationViewBinder @@ -35,18 +36,21 @@ constructor(private val viewModel: NotificationListViewModel) { coroutineScope { launch { var previousKeys = emptySet<HeadsUpRowKey>() - viewModel.pinnedHeadsUpRows + combine(viewModel.pinnedHeadsUpRowKeys, viewModel.activeHeadsUpRowKeys, ::Pair) .sample(viewModel.headsUpAnimationsEnabled, ::Pair) .collect { (newKeys, animationsEnabled) -> - val added = newKeys - previousKeys - val removed = previousKeys - newKeys - previousKeys = newKeys + val pinned = newKeys.first + val all = newKeys.second + val added = all.union(pinned) - previousKeys + val removed = previousKeys - pinned + previousKeys = pinned + Pair(added, removed) if (animationsEnabled) { added.forEach { key -> parentView.generateHeadsUpAnimation( obtainView(key), - /* isHeadsUp = */ true + /* isHeadsUp = */ true, ) } removed.forEach { key -> diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt index 7d5278ed1601..eb1bcc7fe147 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/domain/interactor/HeadsUpNotificationInteractorTest.kt @@ -146,9 +146,17 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_noRows_isEmpty() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + + assertThat(activeHeadsUpRows).isEmpty() + } + + @Test fun pinnedRows_noRows_isEmpty() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) assertThat(pinnedHeadsUpRows).isEmpty() } @@ -156,7 +164,7 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { @Test fun pinnedRows_noPinnedRows_isEmpty() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN no rows are pinned headsUpRepository.setNotifications( fakeHeadsUpRowRepository("key 0"), @@ -170,9 +178,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_noPinnedRows_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN no rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0"), + fakeHeadsUpRowRepository("key 1"), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_hasPinnedRows_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN some rows are pinned val rows = arrayListOf( @@ -188,9 +214,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun pinnedRows_hasPinnedRows_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN no rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsPinned_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // GIVEN some rows are pinned val rows = arrayListOf( @@ -210,9 +254,34 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_rowGetsPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // GIVEN some rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2"), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN all rows are present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + + // WHEN all rows gets pinned + rows[2].isPinned.value = true + runCurrent() + + // THEN no change + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_allRowsPinned_containsAllRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // WHEN all rows are pinned val rows = arrayListOf( @@ -228,9 +297,27 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_allRowsPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // WHEN all rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2", isPinned = true), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // THEN no rows are filtered + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsUnPinned_containsPinnedRows() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) // GIVEN all rows are pinned val rows = arrayListOf( @@ -250,9 +337,31 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() { } @Test + fun activeRows_rowGetsUnPinned_containsAllRows() = + testScope.runTest { + val activeHeadsUpRows by collectLastValue(underTest.activeHeadsUpRowKeys) + // GIVEN all rows are pinned + val rows = + arrayListOf( + fakeHeadsUpRowRepository("key 0", isPinned = true), + fakeHeadsUpRowRepository("key 1", isPinned = true), + fakeHeadsUpRowRepository("key 2", isPinned = true), + ) + headsUpRepository.setNotifications(rows) + runCurrent() + + // WHEN a row gets unpinned + rows[0].isPinned.value = false + runCurrent() + + // THEN all rows are still present + assertThat(activeHeadsUpRows).containsExactly(rows[0], rows[1], rows[2]) + } + + @Test fun pinnedRows_rowGetsPinnedAndUnPinned_containsTheSameInstance() = testScope.runTest { - val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRows) + val pinnedHeadsUpRows by collectLastValue(underTest.pinnedHeadsUpRowKeys) val rows = arrayListOf( |