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

Commit 468736fd authored by András Kurucz's avatar András Kurucz Committed by Android (Google) Code Review
Browse files

Merge "Debounce HeadsUpNotificationInteractor.isHeadsUpOrAnimatingAway" into main

parents 61a65426 1d0df55f
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.advanceTimeBy
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -181,6 +182,7 @@ class SceneContainerStartableTest : SysuiTestCase() {

            kosmos.headsUpNotificationRepository.activeHeadsUpRows.value =
                buildNotificationRows(isPinned = false)
            advanceTimeBy(50L) // account for HeadsUpNotificationInteractor debounce
            assertThat(isVisible).isFalse()
        }

+59 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.coroutines.collectValues
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -278,6 +279,64 @@ class HeadsUpNotificationInteractorTest : SysuiTestCase() {
            assertThat(pinnedHeadsUpRows).containsExactly(rows[0])
        }

    @Test
    fun isHeadsUpOrAnimatingAway_falseOnStart() =
        testScope.runTest {
            val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)

            runCurrent()

            assertThat(isHeadsUpOrAnimatingAway).isFalse()
        }

    @Test
    fun isHeadsUpOrAnimatingAway_hasPinnedRows() =
        testScope.runTest {
            val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)

            // WHEN a row is pinned
            headsUpRepository.setNotifications(fakeHeadsUpRowRepository("key 0", isPinned = true))
            runCurrent()

            assertThat(isHeadsUpOrAnimatingAway).isTrue()
        }

    @Test
    fun isHeadsUpOrAnimatingAway_headsUpAnimatingAway() =
        testScope.runTest {
            val isHeadsUpOrAnimatingAway by collectLastValue(underTest.isHeadsUpOrAnimatingAway)

            // WHEN the last row is animating away
            headsUpRepository.setHeadsUpAnimatingAway(true)
            runCurrent()

            assertThat(isHeadsUpOrAnimatingAway).isTrue()
        }

    @Test
    fun isHeadsUpOrAnimatingAway_headsUpAnimatingAwayDebounced() =
        testScope.runTest {
            val values by collectValues(underTest.isHeadsUpOrAnimatingAway)

            // GIVEN a row is pinned
            headsUpRepository.setNotifications(fakeHeadsUpRowRepository("key 0", isPinned = true))
            runCurrent()
            assertThat(values.size).isEqualTo(2)
            assertThat(values.first()).isFalse() // initial value
            assertThat(values.last()).isTrue()

            // WHEN the last row is removed
            headsUpRepository.setNotifications(emptyList())
            runCurrent()
            // AND starts to animate away
            headsUpRepository.setHeadsUpAnimatingAway(true)
            runCurrent()

            // THEN isHeadsUpOrAnimatingAway remained true
            assertThat(values.size).isEqualTo(2)
            assertThat(values.last()).isTrue()
        }

    @Test
    fun showHeadsUpStatusBar_true() =
        testScope.runTest {
+20 −5
Original line number Diff line number Diff line
@@ -14,7 +14,7 @@
 * limitations under the License.
 */

@file:OptIn(ExperimentalCoroutinesApi::class)
@file:OptIn(ExperimentalCoroutinesApi::class, FlowPreview::class)

package com.android.systemui.statusbar.notification.domain.interactor

@@ -27,11 +27,15 @@ import com.android.systemui.statusbar.notification.data.repository.HeadsUpRowRep
import com.android.systemui.statusbar.notification.shared.HeadsUpRowKey
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart

class HeadsUpNotificationInteractor
@Inject
@@ -77,6 +81,17 @@ constructor(
                animatingAway ->
                hasPinnedRows || animatingAway
            }
            .debounce { isHeadsUpOrAnimatingAway ->
                if (isHeadsUpOrAnimatingAway) {
                    0
                } else {
                    // When the last pinned entry is removed from the [HeadsUpRepository],
                    // there might be a delay before the View starts animating.
                    50L
                }
            }
            .onStart { emit(false) } // emit false, so we don't wait for the initial update
            .distinctUntilChanged()

    private val canShowHeadsUp: Flow<Boolean> =
        combine(