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

Commit b4bcb1e5 authored by Anton Potapov's avatar Anton Potapov Committed by Android (Google) Code Review
Browse files

Merge "Add custom a11y stateDescription for the Spatial Audio button in the Volume Panel" into main

parents 880d0b59 7a6faa3a
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.unit.dp
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.android.compose.animation.Expandable
@@ -64,7 +65,6 @@ class ButtonComponent(
    override fun VolumePanelComposeScope.Content(modifier: Modifier) {
        val viewModelByState by viewModelFlow.collectAsStateWithLifecycle()
        val viewModel = viewModelByState ?: return
        val label = viewModel.label.toString()

        val screenWidth: Float =
            with(LocalDensity.current) { LocalConfiguration.current.screenWidthDp.dp.toPx() }
@@ -81,7 +81,8 @@ class ButtonComponent(
                    modifier =
                        Modifier.fillMaxSize().padding(8.dp).semantics {
                            role = Role.Button
                            contentDescription = label
                            contentDescription = viewModel.label
                            viewModel.stateDescription?.let { stateDescription = it }
                        },
                    color =
                        if (viewModel.isActive) {
@@ -118,7 +119,7 @@ class ButtonComponent(
            }
            Text(
                modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                text = label,
                text = viewModel.label,
                style = MaterialTheme.typography.labelMedium,
                maxLines = 2,
            )
+13 −9
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ import androidx.compose.ui.semantics.clearAndSetSemantics
import androidx.compose.ui.semantics.contentDescription
import androidx.compose.ui.semantics.role
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.semantics.toggleableState
import androidx.compose.ui.state.ToggleableState
import androidx.compose.ui.unit.dp
@@ -59,7 +60,6 @@ class ToggleButtonComponent(
    override fun VolumePanelComposeScope.Content(modifier: Modifier) {
        val viewModelByState by viewModelFlow.collectAsStateWithLifecycle()
        val viewModel = viewModelByState ?: return
        val label = viewModel.label.toString()

        Column(
            modifier = modifier,
@@ -97,13 +97,17 @@ class ToggleButtonComponent(
                    modifier =
                        Modifier.fillMaxSize().padding(8.dp).semantics {
                            role = Role.Switch
                            if (viewModel.stateDescription == null) {
                                toggleableState =
                                    if (viewModel.isActive) {
                                        ToggleableState.On
                                    } else {
                                        ToggleableState.Off
                                    }
                            contentDescription = label
                            } else {
                                stateDescription = viewModel.stateDescription
                            }
                            contentDescription = viewModel.label
                        },
                    onClick = { onCheckedChange(!viewModel.isActive) },
                    shape = RoundedCornerShape(20.dp),
@@ -116,7 +120,7 @@ class ToggleButtonComponent(

            Text(
                modifier = Modifier.clearAndSetSemantics {}.basicMarquee(),
                text = label,
                text = viewModel.label,
                style = MaterialTheme.typography.labelMedium,
                maxLines = 2,
            )
+2 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import com.android.systemui.common.shared.model.Icon
/** Models base buttons appearance. */
data class ButtonViewModel(
    val icon: Icon,
    val label: CharSequence,
    val label: String,
    val isActive: Boolean = true,
    val stateDescription: String? = null,
)
+14 −5
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.systemui.volume.panel.component.spatial.ui.viewmodel

import android.content.Context
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.internal.logging.UiEventLogger
import com.android.systemui.common.shared.model.Icon
import com.android.systemui.dagger.qualifiers.Application
@@ -35,7 +36,6 @@ import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import com.android.app.tracing.coroutines.launchTraced as launch

@VolumePanelScope
class SpatialAudioViewModel
@@ -58,6 +58,7 @@ constructor(
                        isChecked = isEnabled is SpatialAudioEnabledModel.SpatialAudioEnabled,
                        isHeadTrackingAvailable =
                            isAvailable is SpatialAudioAvailabilityModel.HeadTracking,
                        shouldUseLabelInStateDescription = true,
                    )
                    .copy(label = context.getString(R.string.volume_panel_spatial_audio_title))
            }
@@ -94,6 +95,7 @@ constructor(
                                isChecked = isEnabled == currentIsEnabled,
                                isHeadTrackingAvailable =
                                    isAvailable is SpatialAudioAvailabilityModel.HeadTracking,
                                shouldUseLabelInStateDescription = false,
                            )
                        SpatialAudioButtonViewModel(button = buttonViewModel, model = isEnabled)
                    }
@@ -112,7 +114,7 @@ constructor(
                else -> {
                    -1
                }
            }
            },
        )
        scope.launch { interactor.setEnabled(model) }
    }
@@ -120,10 +122,12 @@ constructor(
    private fun SpatialAudioEnabledModel.toViewModel(
        isChecked: Boolean,
        isHeadTrackingAvailable: Boolean,
        shouldUseLabelInStateDescription: Boolean,
    ): ButtonViewModel {
        // This method deliberately uses the same icon for the case when head tracking is disabled
        // to show a toggle button with a non-changing icon
        if (this is SpatialAudioEnabledModel.HeadTrackingEnabled) {
            val label = context.getString(R.string.volume_panel_spatial_audio_tracking)
            return ButtonViewModel(
                isActive = isChecked,
                icon =
@@ -132,11 +136,13 @@ constructor(
                    } else {
                        spatialSpeakerIcon
                    },
                label = context.getString(R.string.volume_panel_spatial_audio_tracking)
                label = label,
                stateDescription = label.takeIf { shouldUseLabelInStateDescription },
            )
        }

        if (this is SpatialAudioEnabledModel.SpatialAudioEnabled) {
            val label = context.getString(R.string.volume_panel_spatial_audio_fixed)
            return ButtonViewModel(
                isActive = isChecked,
                icon =
@@ -145,11 +151,13 @@ constructor(
                    } else {
                        spatialSpeakerIcon
                    },
                label = context.getString(R.string.volume_panel_spatial_audio_fixed)
                label = label,
                stateDescription = label.takeIf { shouldUseLabelInStateDescription },
            )
        }

        if (this is SpatialAudioEnabledModel.Disabled) {
            val label = context.getString(R.string.volume_panel_spatial_audio_off)
            return ButtonViewModel(
                isActive = isChecked,
                icon =
@@ -158,7 +166,8 @@ constructor(
                    } else {
                        spatialSpeakerIcon
                    },
                label = context.getString(R.string.volume_panel_spatial_audio_off)
                label = label,
                stateDescription = label.takeIf { shouldUseLabelInStateDescription },
            )
        }