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

Commit 41f1fa5f authored by Ioana Alexandru's avatar Ioana Alexandru
Browse files

Set up subtitle for Priority modes tile

Bug: 346519570
Test: unit tests + tested manually
Flag: android.app.modes_ui
Change-Id: I93b30811fa39ebdcdf3cea1e305465e8c9fbe4ec
parent fa00cbb6
Loading
Loading
Loading
Loading
+55 −31
Original line number Diff line number Diff line
@@ -22,11 +22,14 @@ import android.platform.test.annotations.DisableFlags
import android.platform.test.annotations.EnableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.notification.data.repository.FakeZenModeRepository
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectValues
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import com.android.systemui.statusbar.policy.data.repository.fakeZenModeRepository
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.flowOf
@@ -40,13 +43,17 @@ import org.junit.runner.RunWith
@SmallTest
@RunWith(AndroidJUnit4::class)
class ModesTileDataInteractorTest : SysuiTestCase() {
    private val zenModeRepository = FakeZenModeRepository()
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val dispatcher = kosmos.testDispatcher
    private val zenModeRepository = kosmos.fakeZenModeRepository

    private val underTest = ModesTileDataInteractor(zenModeRepository)
    private val underTest = ModesTileDataInteractor(zenModeRepository, dispatcher)

    @EnableFlags(Flags.FLAG_MODES_UI)
    @Test
    fun availableWhenFlagIsOn() = runTest {
    fun availableWhenFlagIsOn() =
        testScope.runTest {
            val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())

            assertThat(availability).containsExactly(true)
@@ -54,7 +61,8 @@ class ModesTileDataInteractorTest : SysuiTestCase() {

    @DisableFlags(Flags.FLAG_MODES_UI)
    @Test
    fun unavailableWhenFlagIsOff() = runTest {
    fun unavailableWhenFlagIsOff() =
        testScope.runTest {
            val availability = underTest.availability(TEST_USER).toCollection(mutableListOf())

            assertThat(availability).containsExactly(false)
@@ -62,9 +70,12 @@ class ModesTileDataInteractorTest : SysuiTestCase() {

    @EnableFlags(Flags.FLAG_MODES_UI)
    @Test
    fun isActivatedWhenModesChange() = runTest {
    fun isActivatedWhenModesChange() =
        testScope.runTest {
            val dataList: List<ModesTileModel> by
            collectValues(underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest)))
                collectValues(
                    underTest.tileData(TEST_USER, flowOf(DataUpdateTrigger.InitialRequest))
                )
            runCurrent()
            assertThat(dataList.map { it.isActivated }).containsExactly(false).inOrder()

@@ -72,18 +83,31 @@ class ModesTileDataInteractorTest : SysuiTestCase() {
            zenModeRepository.addMode(id = "One", active = true)
            runCurrent()
            assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder()
            assertThat(dataList.map { it.activeModes }.last()).containsExactly("Mode One")

        // Add another mode: state hasn't changed, so this shouldn't cause another emission
        zenModeRepository.addMode(id = "Two", active = true)
            // Add an inactive mode: state hasn't changed, so this shouldn't cause another emission
            zenModeRepository.addMode(id = "Two", active = false)
            runCurrent()
            assertThat(dataList.map { it.isActivated }).containsExactly(false, true).inOrder()
            assertThat(dataList.map { it.activeModes }.last()).containsExactly("Mode One")

        // Remove a mode and disable the other
            // Add another active mode
            zenModeRepository.addMode(id = "Three", active = true)
            runCurrent()
            assertThat(dataList.map { it.isActivated }).containsExactly(false, true, true).inOrder()
            assertThat(dataList.map { it.activeModes }.last())
                .containsExactly("Mode One", "Mode Three")
                .inOrder()

            // Remove a mode and deactivate the other
            zenModeRepository.removeMode("One")
            runCurrent()
        zenModeRepository.deactivateMode("Two")
            zenModeRepository.deactivateMode("Three")
            runCurrent()
        assertThat(dataList.map { it.isActivated }).containsExactly(false, true, false).inOrder()
            assertThat(dataList.map { it.isActivated })
                .containsExactly(false, true, true, true, false)
                .inOrder()
            assertThat(dataList.map { it.activeModes }.last()).isEmpty()
        }

    private companion object {
+12 −4
Original line number Diff line number Diff line
@@ -54,7 +54,11 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {
    fun handleClick_active() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(data = ModesTileModel(true), expandable = expandable))
            QSTileInputTestKtx.click(
                data = ModesTileModel(true, listOf("DND")),
                expandable = expandable
            )
        )

        verify(mockDialogDelegate).showDialog(eq(expandable))
    }
@@ -63,14 +67,18 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {
    fun handleClick_inactive() = runTest {
        val expandable = mock<Expandable>()
        underTest.handleInput(
            QSTileInputTestKtx.click(data = ModesTileModel(false), expandable = expandable))
            QSTileInputTestKtx.click(
                data = ModesTileModel(false, emptyList()),
                expandable = expandable
            )
        )

        verify(mockDialogDelegate).showDialog(eq(expandable))
    }

    @Test
    fun handleLongClick_active() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true)))
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(true, listOf("DND"))))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
@@ -79,7 +87,7 @@ class ModesTileUserActionInteractorTest : SysuiTestCase() {

    @Test
    fun handleLongClick_inactive() = runTest {
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false)))
        underTest.handleInput(QSTileInputTestKtx.longClick(ModesTileModel(false, emptyList())))

        QSTileIntentUserInputHandlerSubject.assertThat(inputHandler).handledOneIntentInput {
            assertThat(it.intent.action).isEqualTo(Settings.ACTION_ZEN_MODE_SETTINGS)
+17 −3
Original line number Diff line number Diff line
@@ -54,21 +54,35 @@ class ModesTileMapperTest : SysuiTestCase() {

    @Test
    fun inactiveState() {
        val model = ModesTileModel(isActivated = false)
        val model = ModesTileModel(isActivated = false, activeModes = emptyList())

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.INACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_off)
        assertThat(state.secondaryLabel).isEqualTo("No active modes")
    }

    @Test
    fun activeState() {
        val model = ModesTileModel(isActivated = true)
    fun activeState_oneMode() {
        val model = ModesTileModel(isActivated = true, activeModes = listOf("DND"))

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on)
        assertThat(state.secondaryLabel).isEqualTo("DND is active")
    }

    @Test
    fun activeState_multipleModes() {
        val model =
            ModesTileModel(isActivated = true, activeModes = listOf("Mode 1", "Mode 2", "Mode 3"))

        val state = underTest.map(config, model)

        assertThat(state.activationState).isEqualTo(QSTileState.ActivationState.ACTIVE)
        assertThat(state.iconRes).isEqualTo(R.drawable.qs_dnd_icon_on)
        assertThat(state.secondaryLabel).isEqualTo("3 modes are active")
    }
}
+8 −0
Original line number Diff line number Diff line
@@ -1109,6 +1109,14 @@
    <!-- Priority modes: label for a mode that cannot be manually turned on [CHAR LIMIT=35] -->
    <string name="zen_mode_no_manual_invocation">Manage in settings</string>

    <string name="zen_mode_active_modes">
        {count, plural,
            =0 {No active modes}
            =1 {{mode} is active}
            other {# modes are active}
        }
    </string>

    <!-- Zen mode: Priority only introduction message on first use -->
    <string name="zen_priority_introduction">You won\'t be disturbed by sounds and vibrations, except from alarms, reminders, events, and callers you specify. You\'ll still hear anything you choose to play including music, videos, and games.</string>

+15 −5
Original line number Diff line number Diff line
@@ -19,20 +19,27 @@ package com.android.systemui.qs.tiles.impl.modes.domain.interactor
import android.app.Flags
import android.os.UserHandle
import com.android.settingslib.notification.data.repository.ZenModeRepository
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.qs.tiles.base.interactor.DataUpdateTrigger
import com.android.systemui.qs.tiles.base.interactor.QSTileDataInteractor
import com.android.systemui.qs.tiles.impl.modes.domain.model.ModesTileModel
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map

class ModesTileDataInteractor @Inject constructor(val zenModeRepository: ZenModeRepository) :
    QSTileDataInteractor<ModesTileModel> {
    private val zenModeActive =
class ModesTileDataInteractor
@Inject
constructor(
    val zenModeRepository: ZenModeRepository,
    @Background val bgDispatcher: CoroutineDispatcher,
) : QSTileDataInteractor<ModesTileModel> {
    private val activeModes =
        zenModeRepository.modes
            .map { modes -> modes.any { mode -> mode.isActive } }
            .map { modes -> modes.filter { mode -> mode.isActive }.map { it.name } }
            .distinctUntilChanged()

    override fun tileData(
@@ -45,7 +52,10 @@ class ModesTileDataInteractor @Inject constructor(val zenModeRepository: ZenMode
     *
     * TODO(b/299909989): Remove after the transition.
     */
    fun tileData() = zenModeActive.map { ModesTileModel(isActivated = it) }
    fun tileData() =
        activeModes
            .map { ModesTileModel(isActivated = it.isNotEmpty(), activeModes = it) }
            .flowOn(bgDispatcher)

    override fun availability(user: UserHandle): Flow<Boolean> = flowOf(Flags.modesUi())
}
Loading