Loading packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/ui/viewmodel/MediaControlChipViewModel.kt +6 −0 Original line number Diff line number Diff line Loading @@ -78,7 +78,13 @@ private fun toPopupChipModel(model: MediaControlChipModel?, context: Context): P res = com.android.internal.R.drawable.ic_audio_media, contentDescription = contentDescription, ), hoverIcon = Icon.Resource( res = com.android.internal.R.drawable.ic_media_pause, contentDescription = null, ), chipText = model.songName.toString(), isToggled = false, // TODO(b/385202114): Show a popup containing the media carousal when the chip is toggled. onToggle = {}, // TODO(b/385202193): Add support for clicking on the icon on a media chip. Loading packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/shared/model/PopupChipModel.kt +6 −0 Original line number Diff line number Diff line Loading @@ -38,7 +38,13 @@ sealed class PopupChipModel { data class Shown( override val chipId: PopupChipId, /** Default icon displayed on the chip */ val icon: Icon, /** * Icon to be displayed if the chip is hovered. i.e. the mouse pointer is inside the bounds * of the chip. */ val hoverIcon: Icon, val chipText: String, val isToggled: Boolean = false, val onToggle: () -> Unit, Loading packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt 0 → 100644 +111 −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.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.hoverable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsHoveredAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.contentColorFor import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.android.systemui.common.ui.compose.Icon import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel /** * A clickable chip that can show an anchored popup containing relevant system controls. The chip * can show an icon that can have its own separate action distinct from its parent chip. Moreover, * the chip can show text containing contextual information. */ @Composable fun StatusBarPopupChip(model: PopupChipModel.Shown, modifier: Modifier = Modifier) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() val isToggled = model.isToggled Surface( shape = RoundedCornerShape(16.dp), modifier = modifier .hoverable(interactionSource = interactionSource) .padding(vertical = 4.dp) .widthIn(max = 120.dp) .animateContentSize() .clickable(onClick = { model.onToggle() }), color = if (isToggled) { MaterialTheme.colorScheme.primaryContainer } else { MaterialTheme.colorScheme.surfaceContainerHighest }, ) { Row( modifier = Modifier.padding(start = 4.dp, end = 8.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp), ) { val currentIcon = if (isHovered) model.hoverIcon else model.icon val backgroundColor = if (isToggled) { MaterialTheme.colorScheme.primary } else { MaterialTheme.colorScheme.primaryContainer } Icon( icon = currentIcon, modifier = Modifier.background(color = backgroundColor, shape = CircleShape) .clickable( role = Role.Button, onClick = model.onIconPressed, indication = ripple(), interactionSource = remember { MutableInteractionSource() }, ) .padding(2.dp) .size(18.dp), tint = contentColorFor(backgroundColor), ) Text( text = model.chipText, style = MaterialTheme.typography.labelLarge, softWrap = false, overflow = TextOverflow.Ellipsis, ) } } } packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt +7 −4 Original line number Diff line number Diff line Loading @@ -18,10 +18,11 @@ 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.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel /** Container view that holds all right hand side chips in the status bar. */ Loading @@ -29,9 +30,11 @@ import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipM 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) } Row( modifier = Modifier.padding(horizontal = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { chips.forEach { chip -> StatusBarPopupChip(chip) } } } } Loading
packages/SystemUI/src/com/android/systemui/statusbar/featurepods/media/ui/viewmodel/MediaControlChipViewModel.kt +6 −0 Original line number Diff line number Diff line Loading @@ -78,7 +78,13 @@ private fun toPopupChipModel(model: MediaControlChipModel?, context: Context): P res = com.android.internal.R.drawable.ic_audio_media, contentDescription = contentDescription, ), hoverIcon = Icon.Resource( res = com.android.internal.R.drawable.ic_media_pause, contentDescription = null, ), chipText = model.songName.toString(), isToggled = false, // TODO(b/385202114): Show a popup containing the media carousal when the chip is toggled. onToggle = {}, // TODO(b/385202193): Add support for clicking on the icon on a media chip. Loading
packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/shared/model/PopupChipModel.kt +6 −0 Original line number Diff line number Diff line Loading @@ -38,7 +38,13 @@ sealed class PopupChipModel { data class Shown( override val chipId: PopupChipId, /** Default icon displayed on the chip */ val icon: Icon, /** * Icon to be displayed if the chip is hovered. i.e. the mouse pointer is inside the bounds * of the chip. */ val hoverIcon: Icon, val chipText: String, val isToggled: Boolean = false, val onToggle: () -> Unit, Loading
packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChip.kt 0 → 100644 +111 −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.animation.animateContentSize import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.hoverable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsHoveredAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.material3.contentColorFor import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.Role import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import com.android.systemui.common.ui.compose.Icon import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel /** * A clickable chip that can show an anchored popup containing relevant system controls. The chip * can show an icon that can have its own separate action distinct from its parent chip. Moreover, * the chip can show text containing contextual information. */ @Composable fun StatusBarPopupChip(model: PopupChipModel.Shown, modifier: Modifier = Modifier) { val interactionSource = remember { MutableInteractionSource() } val isHovered by interactionSource.collectIsHoveredAsState() val isToggled = model.isToggled Surface( shape = RoundedCornerShape(16.dp), modifier = modifier .hoverable(interactionSource = interactionSource) .padding(vertical = 4.dp) .widthIn(max = 120.dp) .animateContentSize() .clickable(onClick = { model.onToggle() }), color = if (isToggled) { MaterialTheme.colorScheme.primaryContainer } else { MaterialTheme.colorScheme.surfaceContainerHighest }, ) { Row( modifier = Modifier.padding(start = 4.dp, end = 8.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(4.dp), ) { val currentIcon = if (isHovered) model.hoverIcon else model.icon val backgroundColor = if (isToggled) { MaterialTheme.colorScheme.primary } else { MaterialTheme.colorScheme.primaryContainer } Icon( icon = currentIcon, modifier = Modifier.background(color = backgroundColor, shape = CircleShape) .clickable( role = Role.Button, onClick = model.onIconPressed, indication = ripple(), interactionSource = remember { MutableInteractionSource() }, ) .padding(2.dp) .size(18.dp), tint = contentColorFor(backgroundColor), ) Text( text = model.chipText, style = MaterialTheme.typography.labelLarge, softWrap = false, overflow = TextOverflow.Ellipsis, ) } } }
packages/SystemUI/src/com/android/systemui/statusbar/featurepods/popups/ui/compose/StatusBarPopupChipsContainer.kt +7 −4 Original line number Diff line number Diff line Loading @@ -18,10 +18,11 @@ 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.foundation.layout.padding import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipModel /** Container view that holds all right hand side chips in the status bar. */ Loading @@ -29,9 +30,11 @@ import com.android.systemui.statusbar.featurepods.popups.shared.model.PopupChipM 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) } Row( modifier = Modifier.padding(horizontal = 8.dp), verticalAlignment = Alignment.CenterVertically, ) { chips.forEach { chip -> StatusBarPopupChip(chip) } } } }