Loading packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt +3 −5 Original line number Diff line number Diff line Loading @@ -42,9 +42,6 @@ import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource Loading @@ -61,12 +58,13 @@ private const val COLLAPSE_DURATION_MILLIS = 300 @Composable fun ColumnVolumeSliders( viewModels: List<SliderViewModel>, isExpanded: Boolean, onExpandedChanged: (Boolean) -> Unit, sliderColors: PlatformSliderColors, isExpandable: Boolean, modifier: Modifier = Modifier, ) { require(viewModels.isNotEmpty()) var isExpanded: Boolean by remember(isExpandable) { mutableStateOf(!isExpandable) } val transition = updateTransition(isExpanded, label = "CollapsableSliders") Column(modifier = modifier) { Row( Loading @@ -85,7 +83,7 @@ fun ColumnVolumeSliders( if (isExpandable) { ExpandButton( isExpanded = isExpanded, onExpandedChanged = { isExpanded = it }, onExpandedChanged = onExpandedChanged, sliderColors, Modifier, ) Loading packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlidersComponent.kt +3 −0 Original line number Diff line number Diff line Loading @@ -48,8 +48,11 @@ constructor( modifier = modifier.fillMaxWidth(), ) } else { val isExpanded by viewModel.isExpanded.collectAsState() ColumnVolumeSliders( viewModels = sliderViewModels, isExpanded = isExpanded, onExpandedChanged = viewModel::onExpandedChanged, sliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(), isExpandable = isPortrait, modifier = modifier.fillMaxWidth(), Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/model/MediaDeviceSession.kt +4 −0 Original line number Diff line number Diff line Loading @@ -36,3 +36,7 @@ sealed interface MediaDeviceSession { /** Current media state is unknown yet. */ data object Unknown : MediaDeviceSession } /** Returns true when the audio is playing for the [MediaDeviceSession]. */ fun MediaDeviceSession.isPlaying(): Boolean = this is MediaDeviceSession.Active && playbackState?.isActive == true packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt +1 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import com.android.systemui.res.R import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSession import com.android.systemui.volume.panel.component.mediaoutput.domain.model.isPlaying import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel import javax.inject.Inject Loading Loading @@ -110,9 +111,6 @@ constructor( null, ) private fun MediaDeviceSession.isPlaying(): Boolean = this is MediaDeviceSession.Active && playbackState?.isActive == true fun onBarClick(expandable: Expandable) { actionsInteractor.onBarClick(mediaDeviceSession.value, expandable) volumePanelViewModel.dismissPanel() Loading packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +21 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import android.media.AudioManager import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.model.isPlaying import com.android.systemui.volume.panel.component.volume.domain.interactor.CastVolumeInteractor import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel Loading @@ -28,12 +30,17 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch /** * Controls the behaviour of the whole audio Loading @@ -46,6 +53,7 @@ class AudioVolumeComponentViewModel constructor( @VolumePanelScope private val scope: CoroutineScope, castVolumeInteractor: CastVolumeInteractor, mediaOutputInteractor: MediaOutputInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, ) { Loading Loading @@ -90,4 +98,17 @@ constructor( remoteSessionsViewModels + streamViewModels } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private val mutableIsExpanded = MutableSharedFlow<Boolean>() val isExpanded: StateFlow<Boolean> = merge( mutableIsExpanded.onStart { emit(false) }, mediaOutputInteractor.mediaDeviceSession.map { !it.isPlaying() }, ) .stateIn(scope, SharingStarted.Eagerly, false) fun onExpandedChanged(isExpanded: Boolean) { scope.launch { mutableIsExpanded.emit(isExpanded) } } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/ColumnVolumeSliders.kt +3 −5 Original line number Diff line number Diff line Loading @@ -42,9 +42,6 @@ import androidx.compose.material3.IconButtonDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource Loading @@ -61,12 +58,13 @@ private const val COLLAPSE_DURATION_MILLIS = 300 @Composable fun ColumnVolumeSliders( viewModels: List<SliderViewModel>, isExpanded: Boolean, onExpandedChanged: (Boolean) -> Unit, sliderColors: PlatformSliderColors, isExpandable: Boolean, modifier: Modifier = Modifier, ) { require(viewModels.isNotEmpty()) var isExpanded: Boolean by remember(isExpandable) { mutableStateOf(!isExpandable) } val transition = updateTransition(isExpanded, label = "CollapsableSliders") Column(modifier = modifier) { Row( Loading @@ -85,7 +83,7 @@ fun ColumnVolumeSliders( if (isExpandable) { ExpandButton( isExpanded = isExpanded, onExpandedChanged = { isExpanded = it }, onExpandedChanged = onExpandedChanged, sliderColors, Modifier, ) Loading
packages/SystemUI/compose/features/src/com/android/systemui/volume/panel/component/volume/ui/composable/VolumeSlidersComponent.kt +3 −0 Original line number Diff line number Diff line Loading @@ -48,8 +48,11 @@ constructor( modifier = modifier.fillMaxWidth(), ) } else { val isExpanded by viewModel.isExpanded.collectAsState() ColumnVolumeSliders( viewModels = sliderViewModels, isExpanded = isExpanded, onExpandedChanged = viewModel::onExpandedChanged, sliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(), isExpandable = isPortrait, modifier = modifier.fillMaxWidth(), Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/domain/model/MediaDeviceSession.kt +4 −0 Original line number Diff line number Diff line Loading @@ -36,3 +36,7 @@ sealed interface MediaDeviceSession { /** Current media state is unknown yet. */ data object Unknown : MediaDeviceSession } /** Returns true when the audio is playing for the [MediaDeviceSession]. */ fun MediaDeviceSession.isPlaying(): Boolean = this is MediaDeviceSession.Active && playbackState?.isActive == true
packages/SystemUI/src/com/android/systemui/volume/panel/component/mediaoutput/ui/viewmodel/MediaOutputViewModel.kt +1 −3 Original line number Diff line number Diff line Loading @@ -24,6 +24,7 @@ import com.android.systemui.res.R import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputActionsInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.model.MediaDeviceSession import com.android.systemui.volume.panel.component.mediaoutput.domain.model.isPlaying import com.android.systemui.volume.panel.dagger.scope.VolumePanelScope import com.android.systemui.volume.panel.ui.viewmodel.VolumePanelViewModel import javax.inject.Inject Loading Loading @@ -110,9 +111,6 @@ constructor( null, ) private fun MediaDeviceSession.isPlaying(): Boolean = this is MediaDeviceSession.Active && playbackState?.isActive == true fun onBarClick(expandable: Expandable) { actionsInteractor.onBarClick(mediaDeviceSession.value, expandable) volumePanelViewModel.dismissPanel() Loading
packages/SystemUI/src/com/android/systemui/volume/panel/component/volume/ui/viewmodel/AudioVolumeComponentViewModel.kt +21 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,8 @@ package com.android.systemui.volume.panel.component.volume.ui.viewmodel import android.media.AudioManager import com.android.settingslib.volume.shared.model.AudioStream import com.android.systemui.volume.panel.component.mediaoutput.domain.interactor.MediaOutputInteractor import com.android.systemui.volume.panel.component.mediaoutput.domain.model.isPlaying import com.android.systemui.volume.panel.component.volume.domain.interactor.CastVolumeInteractor import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.CastVolumeSliderViewModel Loading @@ -28,12 +30,17 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.transformLatest import kotlinx.coroutines.launch /** * Controls the behaviour of the whole audio Loading @@ -46,6 +53,7 @@ class AudioVolumeComponentViewModel constructor( @VolumePanelScope private val scope: CoroutineScope, castVolumeInteractor: CastVolumeInteractor, mediaOutputInteractor: MediaOutputInteractor, private val streamSliderViewModelFactory: AudioStreamSliderViewModel.Factory, private val castVolumeSliderViewModelFactory: CastVolumeSliderViewModel.Factory, ) { Loading Loading @@ -90,4 +98,17 @@ constructor( remoteSessionsViewModels + streamViewModels } .stateIn(scope, SharingStarted.Eagerly, emptyList()) private val mutableIsExpanded = MutableSharedFlow<Boolean>() val isExpanded: StateFlow<Boolean> = merge( mutableIsExpanded.onStart { emit(false) }, mediaOutputInteractor.mediaDeviceSession.map { !it.isPlaying() }, ) .stateIn(scope, SharingStarted.Eagerly, false) fun onExpandedChanged(isExpanded: Boolean) { scope.launch { mutableIsExpanded.emit(isExpanded) } } }