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

Commit ca2beefc authored by Shawn Lee's avatar Shawn Lee Committed by 0
Browse files

[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
parent 04d09206
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 =
+26 −9
Original line number Diff line number Diff line
@@ -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()) {
+14 −2
Original line number Diff line number Diff line
@@ -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"
            )
        }
    }

+9 −5
Original line number Diff line number Diff line
@@ -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 ->
+116 −7
Original line number Diff line number Diff line
@@ -145,10 +145,18 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(hasPinnedRows).isFalse()
        }

    @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"),
@@ -169,10 +177,28 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).isEmpty()
        }

    @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(
@@ -187,10 +213,28 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).containsExactly(rows[0], rows[1])
        }

    @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(
@@ -209,10 +253,35 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).containsExactly(rows[0], rows[1], rows[2])
        }

    @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(
@@ -227,10 +296,28 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).containsExactly(rows[0], rows[1], rows[2])
        }

    @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(
@@ -249,10 +336,32 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).containsExactly(rows[1], rows[2])
        }

    @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(