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

Commit 03eedf01 authored by Caitlin Shkuratov's avatar Caitlin Shkuratov Committed by Android (Google) Code Review
Browse files

Merge "[SB][Chips] Support notif icons in Compose chips for connected displays" into main

parents 63b2fd9f e5cee22c
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -19,8 +19,6 @@ package com.android.systemui.statusbar.chips.ui.compose
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.Measurable
+54 −22
Original line number Diff line number Diff line
@@ -49,11 +49,18 @@ import com.android.systemui.animation.Expandable
import com.android.systemui.common.ui.compose.Icon
import com.android.systemui.common.ui.compose.load
import com.android.systemui.res.R
import com.android.systemui.statusbar.StatusBarIconView
import com.android.systemui.statusbar.chips.ui.model.ColorsModel
import com.android.systemui.statusbar.chips.ui.model.OngoingActivityChipModel
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder

@Composable
fun OngoingActivityChip(model: OngoingActivityChipModel.Active, modifier: Modifier = Modifier) {
fun OngoingActivityChip(
    model: OngoingActivityChipModel.Active,
    iconViewStore: NotificationIconContainerViewBinder.IconViewStore?,
    modifier: Modifier = Modifier,
) {
    when (val clickBehavior = model.clickBehavior) {
        is OngoingActivityChipModel.ClickBehavior.ExpandAction -> {
            // Wrap the chip in an Expandable so we can animate the expand transition.
@@ -65,15 +72,15 @@ fun OngoingActivityChip(model: OngoingActivityChipModel.Active, modifier: Modifi
                    ),
                modifier = modifier,
            ) { expandable ->
                ChipBody(model, onClick = { clickBehavior.onClick(expandable) })
                ChipBody(model, iconViewStore, onClick = { clickBehavior.onClick(expandable) })
            }
        }
        is OngoingActivityChipModel.ClickBehavior.ShowHeadsUpNotification -> {
            ChipBody(model, onClick = { clickBehavior.onClick() })
            ChipBody(model, iconViewStore, onClick = { clickBehavior.onClick() })
        }

        is OngoingActivityChipModel.ClickBehavior.None -> {
            ChipBody(model, modifier = modifier)
            ChipBody(model, iconViewStore, modifier = modifier)
        }
    }
}
@@ -81,12 +88,15 @@ fun OngoingActivityChip(model: OngoingActivityChipModel.Active, modifier: Modifi
@Composable
private fun ChipBody(
    model: OngoingActivityChipModel.Active,
    iconViewStore: NotificationIconContainerViewBinder.IconViewStore?,
    modifier: Modifier = Modifier,
    onClick: (() -> Unit)? = null,
) {
    val context = LocalContext.current
    val isClickable = onClick != null
    val hasEmbeddedIcon = model.icon is OngoingActivityChipModel.ChipIcon.StatusBarView
    val hasEmbeddedIcon =
        model.icon is OngoingActivityChipModel.ChipIcon.StatusBarView ||
            model.icon is OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon
    val contentDescription =
        when (val icon = model.icon) {
            is OngoingActivityChipModel.ChipIcon.StatusBarView -> icon.contentDescription.load()
@@ -156,7 +166,9 @@ private fun ChipBody(
                            }
                    ),
        ) {
            model.icon?.let { ChipIcon(viewModel = it, colors = model.colors) }
            model.icon?.let {
                ChipIcon(viewModel = it, iconViewStore = iconViewStore, colors = model.colors)
            }

            val isIconOnly = model is OngoingActivityChipModel.Active.IconOnly
            if (!isIconOnly) {
@@ -169,6 +181,7 @@ private fun ChipBody(
@Composable
private fun ChipIcon(
    viewModel: OngoingActivityChipModel.ChipIcon,
    iconViewStore: NotificationIconContainerViewBinder.IconViewStore?,
    colors: ColorsModel,
    modifier: Modifier = Modifier,
) {
@@ -176,22 +189,16 @@ private fun ChipIcon(

    when (viewModel) {
        is OngoingActivityChipModel.ChipIcon.StatusBarView -> {
            // TODO(b/364653005): If the notification updates their small icon, ensure it's updated
            // in the chip.
            val originalIcon = viewModel.impl
            val iconSizePx =
                context.resources.getDimensionPixelSize(
                    R.dimen.ongoing_activity_chip_embedded_padding_icon_size
                )
            AndroidView(
                modifier = modifier,
                factory = { _ ->
                    originalIcon.apply {
                        layoutParams = ViewGroup.LayoutParams(iconSizePx, iconSizePx)
                        imageTintList = ColorStateList.valueOf(colors.text(context))
            StatusBarConnectedDisplays.assertInLegacyMode()
            StatusBarIcon(colors, viewModel.impl.notification?.key, modifier) { viewModel.impl }
        }
        is OngoingActivityChipModel.ChipIcon.StatusBarNotificationIcon -> {
            StatusBarConnectedDisplays.assertInNewMode()
            check(iconViewStore != null)

            StatusBarIcon(colors, viewModel.notificationKey, modifier) {
                iconViewStore.iconView(viewModel.notificationKey)
            }
                },
            )
        }

        is OngoingActivityChipModel.ChipIcon.SingleColorIcon -> {
@@ -209,6 +216,31 @@ private fun ChipIcon(
    }
}

/** A Compose wrapper around [StatusBarIconView]. */
@Composable
private fun StatusBarIcon(
    colors: ColorsModel,
    notificationKey: String?,
    modifier: Modifier = Modifier,
    iconFactory: () -> StatusBarIconView?,
) {
    val context = LocalContext.current

    val iconSizePx =
        context.resources.getDimensionPixelSize(
            R.dimen.ongoing_activity_chip_embedded_padding_icon_size
        )
    AndroidView(
        modifier = modifier,
        factory = { _ ->
            iconFactory.invoke()?.apply {
                layoutParams = ViewGroup.LayoutParams(iconSizePx, iconSizePx)
                imageTintList = ColorStateList.valueOf(colors.text(context))
            } ?: throw IllegalStateException("Missing StatusBarIconView for $notificationKey")
        },
    )
}

@Composable
private fun ExpandableChip(
    color: () -> Color,
+9 −3
Original line number Diff line number Diff line
@@ -26,18 +26,24 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.android.systemui.statusbar.chips.ui.model.MultipleOngoingActivityChipsModel
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder

@Composable
fun OngoingActivityChips(chips: MultipleOngoingActivityChipsModel, modifier: Modifier = Modifier) {
fun OngoingActivityChips(
    chips: MultipleOngoingActivityChipsModel,
    iconViewStore: NotificationIconContainerViewBinder.IconViewStore?,
    modifier: Modifier = Modifier,
) {
    Row(
        // TODO(b/372657935): Remove magic numbers for padding and spacing.
        modifier = modifier.fillMaxHeight().padding(horizontal = 6.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(8.dp),
    ) {
        // TODO(b/372657935): Make sure chips are only shown when there is enough horizontal space.
        chips.active
            .filter { !it.isHidden }
            .forEach { key(it.key) { OngoingActivityChip(model = it) } }
            .forEach {
                key(it.key) { OngoingActivityChip(model = it, iconViewStore = iconViewStore) }
            }
    }
}
+4 −4
Original line number Diff line number Diff line
@@ -222,10 +222,6 @@ constructor(
                return@traceSection
            }

            if (StatusBarConnectedDisplays.isEnabled) {
                onIconUpdateRequiredListeners.onEach { it.onIconUpdateRequired(entry) }
            }

            if (usingCache && !Flags.notificationsBackgroundIcons()) {
                Log.wtf(
                    TAG,
@@ -238,6 +234,10 @@ constructor(
                entry.icons.peopleAvatarDescriptor = null
            }

            if (StatusBarConnectedDisplays.isEnabled) {
                onIconUpdateRequiredListeners.onEach { it.onIconUpdateRequired(entry) }
            }

            val (normalIconDescriptor, sensitiveIconDescriptor) = getIconDescriptors(entry)
            val notificationContentDescription =
                entry.sbn.notification?.let { iconBuilder.getIconContentDescription(it) }
+18 −1
Original line number Diff line number Diff line
@@ -41,12 +41,15 @@ import com.android.systemui.plugins.DarkIconDispatcher
import com.android.systemui.res.R
import com.android.systemui.statusbar.chips.ui.compose.OngoingActivityChips
import com.android.systemui.statusbar.core.NewStatusBarIcons
import com.android.systemui.statusbar.core.StatusBarConnectedDisplays
import com.android.systemui.statusbar.core.StatusBarRootModernization
import com.android.systemui.statusbar.data.repository.DarkIconDispatcherStore
import com.android.systemui.statusbar.events.domain.interactor.SystemStatusEventAnimationInteractor
import com.android.systemui.statusbar.featurepods.popups.StatusBarPopupChips
import com.android.systemui.statusbar.featurepods.popups.ui.compose.StatusBarPopupChipsContainer
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.ConnectedDisplaysStatusBarNotificationIconViewStore
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerStatusBarViewBinder
import com.android.systemui.statusbar.notification.icon.ui.viewbinder.NotificationIconContainerViewBinder
import com.android.systemui.statusbar.phone.NotificationIconContainer
import com.android.systemui.statusbar.phone.PhoneStatusBarView
import com.android.systemui.statusbar.phone.StatusBarLocation
@@ -72,6 +75,7 @@ constructor(
    private val homeStatusBarViewModelFactory: HomeStatusBarViewModelFactory,
    private val homeStatusBarViewBinder: HomeStatusBarViewBinder,
    private val notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
    private val iconViewStoreFactory: ConnectedDisplaysStatusBarNotificationIconViewStore.Factory,
    private val darkIconManagerFactory: DarkIconManager.Factory,
    private val iconController: StatusBarIconController,
    private val ongoingCallController: OngoingCallController,
@@ -89,6 +93,7 @@ constructor(
                    statusBarViewModelFactory = homeStatusBarViewModelFactory,
                    statusBarViewBinder = homeStatusBarViewBinder,
                    notificationIconsBinder = notificationIconsBinder,
                    iconViewStoreFactory = iconViewStoreFactory,
                    darkIconManagerFactory = darkIconManagerFactory,
                    iconController = iconController,
                    ongoingCallController = ongoingCallController,
@@ -119,6 +124,7 @@ fun StatusBarRoot(
    statusBarViewModelFactory: HomeStatusBarViewModelFactory,
    statusBarViewBinder: HomeStatusBarViewBinder,
    notificationIconsBinder: NotificationIconContainerStatusBarViewBinder,
    iconViewStoreFactory: ConnectedDisplaysStatusBarNotificationIconViewStore.Factory,
    darkIconManagerFactory: DarkIconManager.Factory,
    iconController: StatusBarIconController,
    ongoingCallController: OngoingCallController,
@@ -129,6 +135,14 @@ fun StatusBarRoot(
    val displayId = parent.context.displayId
    val statusBarViewModel =
        rememberViewModel("HomeStatusBar") { statusBarViewModelFactory.create(displayId) }
    val iconViewStore: NotificationIconContainerViewBinder.IconViewStore? =
        if (StatusBarConnectedDisplays.isEnabled) {
            rememberViewModel("HomeStatusBar.IconViewStore[$displayId]") {
                iconViewStoreFactory.create(displayId)
            }
        } else {
            null
        }

    Box(Modifier.fillMaxSize()) {
        // TODO(b/364360986): remove this before rolling the flag forward
@@ -174,7 +188,10 @@ fun StatusBarRoot(
                                        val chips by
                                            statusBarViewModel.ongoingActivityChips
                                                .collectAsStateWithLifecycle()
                                        OngoingActivityChips(chips = chips)
                                        OngoingActivityChips(
                                            chips = chips,
                                            iconViewStore = iconViewStore,
                                        )
                                    }
                                }
                            }