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

Commit 04ea6705 authored by amehfooz's avatar amehfooz
Browse files

[ROSP] Add a container for StatusBarPopupChips to the status bar

This CL adds a composable container in status_bar.xml that will
be used to display StatusBarPopupChips. The container currently
shows the song name as plain text.

Also, adds support for the MediaControlChip in
StatusBarPopupChipsViewModel. The
`StatusBarPopupChipsViewModel.shownPopupChips` StateFlow is
used in StatusBarRoot to update the `StatusBarPopupChipsContainer`.

Test: Play media -> Verify the song name is displayed on the top right
in the status bar.
Bug: b/385245633
Flag: com.android.systemui.status_bar_popup_chips
Change-Id: I5bc4e28104bacbf0846a7e5527fa399ae64607ad
parent b1ec019b
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -22,6 +22,10 @@ import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.media.controls.shared.model.MediaDataLoadingModel
import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipId
import com.android.systemui.statusbar.featurepods.popups.StatusBarPopupChips
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
@@ -35,12 +39,28 @@ import org.junit.runner.RunWith
class StatusBarPopupChipsViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val mediaFilterRepository = kosmos.mediaFilterRepository
    private val underTest = kosmos.statusBarPopupChipsViewModel

    @Test
    fun popupChips_allHidden_empty() =
    fun shownPopupChips_allHidden_empty() =
        testScope.runTest {
            val latest by collectLastValue(underTest.popupChips)
            assertThat(latest).isEmpty()
            val shownPopupChips by collectLastValue(underTest.shownPopupChips)
            assertThat(shownPopupChips).isEmpty()
        }

    @Test
    fun shownPopupChips_activeMedia_restHidden_mediaControlChipShown() =
        testScope.runTest {
            val shownPopupChips by collectLastValue(underTest.shownPopupChips)

            val userMedia = MediaData(active = true, song = "test")
            val instanceId = userMedia.instanceId

            mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
            mediaFilterRepository.addMediaDataLoadingState(MediaDataLoadingModel.Loaded(instanceId))

            assertThat(shownPopupChips).hasSize(1)
            assertThat(shownPopupChips!!.first().chipId).isEqualTo(PopupChipId.MediaControl)
        }
}
+3 −0
Original line number Diff line number Diff line
@@ -23,6 +23,7 @@ import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.events.shared.model.SystemEventAnimationState.Idle
import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
@@ -41,6 +42,8 @@ class FakeHomeStatusBarViewModel(

    override val ongoingActivityChips = MutableStateFlow(MultipleOngoingActivityChipsModel())

    override val statusBarPopupChips = MutableStateFlow(emptyList<PopupChipModel.Shown>())

    override val isHomeStatusBarAllowedByScene = MutableStateFlow(false)

    override val shouldShowOperatorNameView = MutableStateFlow(false)
+3 −3
Original line number Diff line number Diff line
@@ -58,18 +58,18 @@ constructor(
            .stateIn(
                backgroundScope,
                SharingStarted.WhileSubscribed(),
                PopupChipModel.Hidden(PopupChipId.MediaControls),
                PopupChipModel.Hidden(PopupChipId.MediaControl),
            )
}

private fun toPopupChipModel(model: MediaControlChipModel?, context: Context): PopupChipModel {
    if (model == null || model.songName.isNullOrEmpty()) {
        return PopupChipModel.Hidden(PopupChipId.MediaControls)
        return PopupChipModel.Hidden(PopupChipId.MediaControl)
    }

    val contentDescription = model.appName?.let { ContentDescription.Loaded(description = it) }
    return PopupChipModel.Shown(
        chipId = PopupChipId.MediaControls,
        chipId = PopupChipId.MediaControl,
        icon =
            model.appIcon?.loadDrawable(context)?.let {
                Icon.Loaded(drawable = it, contentDescription = contentDescription)
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import com.android.systemui.common.shared.model.Icon
 * displaying its popup at a time.
 */
sealed class PopupChipId(val value: String) {
    data object MediaControls : PopupChipId("MediaControls")
    data object MediaControl : PopupChipId("MediaControl")
}

/** Model for individual status bar popup chips. */
+37 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.statusbar.featurepods.popups.ui.compose

import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Row
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel

/** Container view that holds all right hand side chips in the status bar. */
@Composable
fun StatusBarPopupChipsContainer(chips: List<PopupChipModel.Shown>, modifier: Modifier = Modifier) {
    //    TODO(b/385353140): Add padding and spacing for this container according to UX specs.
    Box {
        Row(verticalAlignment = Alignment.CenterVertically) {
            // TODO(b/385352859): Show `StatusBarPopupChip` here instead of `Text` once it is ready.
            chips.forEach { chip -> Text(text = chip.chipText) }
        }
    }
}
Loading