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

Commit 66f5c901 authored by Luna Zhang's avatar Luna Zhang
Browse files

Add volume slider to shade

Test: Manually verified the volume slider shows up in shade
Flag: com.android.systemui.qs_tile_detailed_view
Bug: b/378513663
Change-Id: Ie868479c4e10ad9e81afd061c484af1dcf376af8
parent 5cc5e8e8
Loading
Loading
Loading
Loading
+43 −9
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ import androidx.compose.ui.layout.onPlaced
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.compose.PlatformSliderDefaults
import com.android.compose.animation.scene.ContentScope
import com.android.compose.animation.scene.ElementKey
import com.android.compose.animation.scene.UserAction
@@ -80,8 +82,11 @@ import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrim
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
import com.android.systemui.statusbar.notification.stack.ui.view.NotificationScrollView
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
import com.android.systemui.volume.panel.component.volume.ui.composable.VolumeSlider
import dagger.Lazy
import javax.inject.Inject
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.Flow

@SysUISingleton
@@ -90,7 +95,7 @@ class QuickSettingsShadeOverlay
constructor(
    private val actionsViewModelFactory: QuickSettingsShadeOverlayActionsViewModel.Factory,
    private val contentViewModelFactory: QuickSettingsShadeOverlayContentViewModel.Factory,
    private val quickSettingsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory,
    quickSettingsContainerViewModelFactory: QuickSettingsContainerViewModel.Factory,
    private val notificationStackScrollView: Lazy<NotificationScrollView>,
    private val notificationsPlaceholderViewModelFactory: NotificationsPlaceholderViewModel.Factory,
) : Overlay {
@@ -103,8 +108,19 @@ constructor(

    override val userActions: Flow<Map<UserAction, UserActionResult>> = actionsViewModel.actions

    private val quickSettingsContainerViewModel by lazy {
        quickSettingsContainerViewModelFactory.create(
            supportsBrightnessMirroring = true,
            expansion = COLLAPSED,
        )
    }

    override suspend fun activate(): Nothing {
        actionsViewModel.activate()
        coroutineScope {
            launch { quickSettingsContainerViewModel.activate() }
            launch { actionsViewModel.activate() }
        }
        awaitCancellation()
    }

    @Composable
@@ -113,13 +129,6 @@ constructor(
            rememberViewModel("QuickSettingsShadeOverlayContent") {
                contentViewModelFactory.create()
            }
        val quickSettingsContainerViewModel =
            rememberViewModel("QuickSettingsShadeOverlayContainer") {
                quickSettingsContainerViewModelFactory.create(
                    supportsBrightnessMirroring = true,
                    expansion = COLLAPSED,
                )
            }
        val hunPlaceholderViewModel =
            rememberViewModel("QuickSettingsShadeOverlayPlaceholder") {
                notificationsPlaceholderViewModelFactory.create()
@@ -278,6 +287,31 @@ fun ContentScope.QuickSettingsLayout(
                )
            }

            val volumeSliderViewModel = viewModel.volumeSliderViewModel
            if (volumeSliderViewModel != null) {
                val volumeSliderState by volumeSliderViewModel.slider.collectAsStateWithLifecycle()

                Box(
                    Modifier.systemGestureExclusionInShade(
                        enabled = { layoutState.transitionState is TransitionState.Idle }
                    )
                ) {
                    VolumeSlider(
                        modifier = Modifier.fillMaxWidth(),
                        showLabel = false,
                        state = volumeSliderState,
                        onValueChange = { newValue: Float ->
                            volumeSliderViewModel.onValueChanged(volumeSliderState, newValue)
                        },
                        onValueChangeFinished = { volumeSliderViewModel.onValueChangeFinished() },
                        onIconTapped = { volumeSliderViewModel.toggleMuted(volumeSliderState) },
                        sliderColors = PlatformSliderDefaults.defaultPlatformSliderColors(),
                        hapticsViewModelFactory =
                            volumeSliderViewModel.getSliderHapticsViewModelFactory(),
                    )
                }
            }

            Box {
                GridAnchor()
                TileGrid(
+9 −6
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ fun VolumeSlider(
    hapticsViewModelFactory: SliderHapticsViewModel.Factory?,
    onValueChangeFinished: (() -> Unit)? = null,
    button: (@Composable RowScope.() -> Unit)? = null,
    showLabel: Boolean = true,
) {
    if (!Flags.volumeRedesign()) {
        LegacyVolumeSlider(
@@ -114,12 +115,14 @@ fun VolumeSlider(
    }

    Column(modifier = modifier.animateContentSize()) {
        if (showLabel) {
            Text(
                text = state.label,
                style = MaterialTheme.typography.titleMedium,
                color = MaterialTheme.colorScheme.onSurface,
                modifier = Modifier.fillMaxWidth().clearAndSetSemantics {},
            )
        }
        Row(
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp),
+30 −1
Original line number Diff line number Diff line
@@ -16,7 +16,10 @@

package com.android.systemui.qs.ui.viewmodel

import android.content.Context
import android.media.AudioManager
import androidx.compose.runtime.getValue
import com.android.settingslib.volume.shared.model.AudioStream
import com.android.systemui.brightness.ui.viewmodel.BrightnessSliderViewModel
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
@@ -24,11 +27,16 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarou
import com.android.systemui.media.controls.ui.controller.MediaCarouselController
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.dagger.MediaModule
import com.android.systemui.qs.flags.QsDetailedView
import com.android.systemui.qs.panels.ui.viewmodel.DetailsViewModel
import com.android.systemui.qs.panels.ui.viewmodel.EditModeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.ToolbarViewModel
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
import com.android.systemui.volume.panel.component.volume.domain.model.SliderType
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.AudioStreamSliderViewModel
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -40,10 +48,12 @@ import kotlinx.coroutines.launch
class QuickSettingsContainerViewModel
@AssistedInject
constructor(
    @ShadeDisplayAware shadeContext: Context,
    brightnessSliderViewModelFactory: BrightnessSliderViewModel.Factory,
    private val audioStreamSliderViewModelFactory: AudioStreamSliderViewModel.Factory,
    shadeHeaderViewModelFactory: ShadeHeaderViewModel.Factory,
    tileGridViewModelFactory: TileGridViewModel.Factory,
    @Assisted supportsBrightnessMirroring: Boolean,
    @Assisted private val supportsBrightnessMirroring: Boolean,
    @Assisted private val expansion: Float?,
    val editModeViewModel: EditModeViewModel,
    val detailsViewModel: DetailsViewModel,
@@ -58,6 +68,12 @@ constructor(
    val brightnessSliderViewModel =
        brightnessSliderViewModelFactory.create(supportsBrightnessMirroring)

    private val showVolumeSlider =
        QsDetailedView.isEnabled &&
            shadeContext.resources.getBoolean(R.bool.config_enableDesktopAudioTileDetailsView)

    var volumeSliderViewModel: AudioStreamSliderViewModel? = null

    val toolbarViewModel = toolbarViewModelFactory.create()

    val shadeHeaderViewModel = shadeHeaderViewModelFactory.create()
@@ -72,6 +88,19 @@ constructor(

    override suspend fun onActivated(): Nothing {
        coroutineScope {
            if (showVolumeSlider) {
                val volumeSliderStream =
                    SliderType.Stream(AudioStream(AudioManager.STREAM_MUSIC)).stream
                launch {
                    volumeSliderViewModel =
                        audioStreamSliderViewModelFactory.create(
                            AudioStreamSliderViewModel.FactoryAudioStreamWrapper(
                                volumeSliderStream
                            ),
                            this,
                        )
                }
            }
            expansion?.let { mediaHost.expansion = it }
            launch { hydrator.activate() }
            launch { brightnessSliderViewModel.activate() }
+4 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.qs.ui.viewmodel

import android.content.applicationContext
import com.android.systemui.brightness.ui.viewmodel.brightnessSliderViewModelFactory
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
@@ -26,6 +27,7 @@ import com.android.systemui.qs.panels.ui.viewmodel.editModeViewModel
import com.android.systemui.qs.panels.ui.viewmodel.tileGridViewModelFactory
import com.android.systemui.qs.panels.ui.viewmodel.toolbar.toolbarViewModelFactory
import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory
import com.android.systemui.volume.panel.component.volume.slider.ui.viewmodel.audioStreamSliderViewModelFactory
import org.mockito.kotlin.mock

val Kosmos.quickSettingsContainerViewModelFactory by
@@ -36,7 +38,9 @@ val Kosmos.quickSettingsContainerViewModelFactory by
                expansion: Float?,
            ): QuickSettingsContainerViewModel {
                return QuickSettingsContainerViewModel(
                    shadeContext = applicationContext,
                    brightnessSliderViewModelFactory = brightnessSliderViewModelFactory,
                    audioStreamSliderViewModelFactory = audioStreamSliderViewModelFactory,
                    shadeHeaderViewModelFactory = shadeHeaderViewModelFactory,
                    tileGridViewModelFactory = tileGridViewModelFactory,
                    supportsBrightnessMirroring = supportsBrightnessMirroring,