From 5d4b99a56c1c6ecbf573d2cb96d72d4dffeb6a24 Mon Sep 17 00:00:00 2001 From: Rajat Biswas Date: Tue, 24 Sep 2024 07:19:00 +0000 Subject: [PATCH] Update Uamp Player Screen bottom buttons layout --- media/sample/build.gradle.kts | 1 + .../mediasample/ui/player/FavoriteButton.kt | 3 + .../ui/player/UampSettingsButtons.kt | 27 +++- .../UampMediaPlayerA11yScreenshotTest.kt | 126 ++++++++++++++++++ .../media/ui/screens/player/PlayerScreen.kt | 6 +- 5 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 media/sample/src/test/java/com/google/android/horologist/mediasample/ui/player/UampMediaPlayerA11yScreenshotTest.kt diff --git a/media/sample/build.gradle.kts b/media/sample/build.gradle.kts index 0aa065f1b0..2e42ccd073 100644 --- a/media/sample/build.gradle.kts +++ b/media/sample/build.gradle.kts @@ -263,6 +263,7 @@ dependencies { testImplementation(libs.dagger.hiltandroidtesting) kspTest(libs.dagger.hiltandroidcompiler) testImplementation(libs.androidx.work.testing) + testImplementation(projects.roboscreenshots) androidTestImplementation(platform(libs.compose.bom)) androidTestImplementation(libs.compose.ui.test.junit4) diff --git a/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/FavoriteButton.kt b/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/FavoriteButton.kt index b82189f6c1..4fb935594e 100644 --- a/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/FavoriteButton.kt +++ b/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/FavoriteButton.kt @@ -24,6 +24,7 @@ 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.stringResource import com.google.android.horologist.audio.ui.components.actions.SettingsButton @@ -37,6 +38,7 @@ import com.google.android.horologist.mediasample.R @Composable public fun FavoriteButton( modifier: Modifier = Modifier, + iconAlignment: Alignment = Alignment.Center, ) { var faved by remember { mutableStateOf(false) } SettingsButton( @@ -44,5 +46,6 @@ public fun FavoriteButton( onClick = { faved = !faved }, imageVector = if (faved) Icons.Default.Favorite else Icons.Default.FavoriteBorder, contentDescription = stringResource(R.string.favorite_content_description), + iconAlignment = iconAlignment, ) } diff --git a/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/UampSettingsButtons.kt b/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/UampSettingsButtons.kt index 201c1b50ee..378980d32b 100644 --- a/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/UampSettingsButtons.kt +++ b/media/sample/src/main/java/com/google/android/horologist/mediasample/ui/player/UampSettingsButtons.kt @@ -18,9 +18,14 @@ package com.google.android.horologist.mediasample.ui.player import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.unit.dp import com.google.android.horologist.audio.ui.VolumeUiState import com.google.android.horologist.audio.ui.components.AudioOutputUi import com.google.android.horologist.audio.ui.components.SettingsButtonsDefaults @@ -39,22 +44,38 @@ public fun UampSettingsButtons( modifier: Modifier = Modifier, enabled: Boolean = true, ) { + val configuration = LocalConfiguration.current + val verticalPadding = (configuration.screenWidthDp * VERTICAL_PADDING_SCREEN_PERCENTAGE).dp + Row( - modifier = modifier, + modifier = modifier + .fillMaxSize() + .padding(vertical = verticalPadding), verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceEvenly, + horizontalArrangement = Arrangement.Center, ) { - FavoriteButton() + FavoriteButton( + modifier = Modifier.weight(1f), + iconAlignment = Alignment.TopCenter, + ) SettingsButtonsDefaults.BrandIcon( + modifier = Modifier + .align(Alignment.Bottom) + .weight(1f) + .size(16.dp), iconId = R.drawable.ic_stat_horologist, enabled = enabled, ) SetAudioOutputButton( + modifier = Modifier.weight(1f), onVolumeClick = onVolumeClick, volumeUiState = volumeUiState, audioOutputUi = audioOutputUi, + iconAlignment = Alignment.TopCenter, ) } } + +private const val VERTICAL_PADDING_SCREEN_PERCENTAGE = 0.026f diff --git a/media/sample/src/test/java/com/google/android/horologist/mediasample/ui/player/UampMediaPlayerA11yScreenshotTest.kt b/media/sample/src/test/java/com/google/android/horologist/mediasample/ui/player/UampMediaPlayerA11yScreenshotTest.kt new file mode 100644 index 0000000000..061fcc07c9 --- /dev/null +++ b/media/sample/src/test/java/com/google/android/horologist/mediasample/ui/player/UampMediaPlayerA11yScreenshotTest.kt @@ -0,0 +1,126 @@ +/* + * Copyright 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 + * + * https://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.google.android.horologist.mediasample.ui.player + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.ui.Modifier +import androidx.wear.compose.material.MaterialTheme +import com.google.android.horologist.audio.AudioOutput +import com.google.android.horologist.audio.ui.VolumeUiState +import com.google.android.horologist.audio.ui.components.toAudioOutputUi +import com.google.android.horologist.media.ui.components.animated.AnimatedMediaControlButtons +import com.google.android.horologist.media.ui.components.animated.AnimatedMediaInfoDisplay +import com.google.android.horologist.media.ui.components.background.ArtworkColorBackground +import com.google.android.horologist.media.ui.screens.player.PlayerScreen +import com.google.android.horologist.media.ui.state.PlayerUiState +import com.google.android.horologist.media.ui.state.model.MediaUiModel +import com.google.android.horologist.media.ui.state.model.TrackPositionUiModel +import com.google.android.horologist.media.ui.uamp.UampTheme +import com.google.android.horologist.screenshots.rng.WearLegacyA11yTest +import org.junit.Test +import org.robolectric.annotation.Config +import kotlin.time.Duration.Companion.seconds + +class UampMediaPlayerA11yScreenshotTest : WearLegacyA11yTest() { + + @Test + fun mediaPlayerLargeRound() { + uampMediaPlayerScreen() + } + + @Config( + qualifiers = "+w192dp-h192dp", + ) + @Test + fun mediaPlayerSmallRound() { + uampMediaPlayerScreen() + } + + private fun uampMediaPlayerScreen() { + val playerUiState = PlayerUiState( + playEnabled = true, + pauseEnabled = true, + seekBackEnabled = true, + seekForwardEnabled = true, + seekInCurrentMediaItemEnabled = true, + seekToPreviousEnabled = false, + seekToNextEnabled = true, + shuffleEnabled = false, + shuffleOn = false, + playPauseEnabled = true, + playing = true, + media = MediaUiModel.Ready( + id = "", + title = "Weather with You", + subtitle = "Crowded House", + ), + trackPositionUiModel = TrackPositionUiModel.Actual( + percent = 0.133f, + position = 30.seconds, + duration = 225.seconds, + ), + connected = true, + ) + + val volumeUiState = VolumeUiState(current = 1) + + val audioOutput = AudioOutput.BluetoothHeadset( + id = "bt0", + name = "BT_Headphone" + ) + + runScreenTest { + UampTheme { + PlayerScreen( + mediaDisplay = { + AnimatedMediaInfoDisplay( + media = playerUiState.media, + loading = !playerUiState.connected || playerUiState.media is MediaUiModel.Loading, + ) + }, + controlButtons = { + AnimatedMediaControlButtons( + onPlayButtonClick = { }, + onPauseButtonClick = { }, + playPauseButtonEnabled = playerUiState.playPauseEnabled, + playing = playerUiState.playing, + onSeekToPreviousButtonClick = { }, + seekToPreviousButtonEnabled = playerUiState.seekToPreviousEnabled, + onSeekToNextButtonClick = { }, + seekToNextButtonEnabled = playerUiState.seekToNextEnabled, + trackPositionUiModel = playerUiState.trackPositionUiModel, + ) + }, + buttons = { + UampSettingsButtons( + volumeUiState = volumeUiState, + audioOutputUi = audioOutput.toAudioOutputUi(), + onVolumeClick = { }, + ) + }, + background = { + ArtworkColorBackground( + paintable = null, + defaultColor = MaterialTheme.colors.primary, + modifier = Modifier.fillMaxSize(), + ) + }, + ) + } + } + } +} diff --git a/media/ui/src/main/java/com/google/android/horologist/media/ui/screens/player/PlayerScreen.kt b/media/ui/src/main/java/com/google/android/horologist/media/ui/screens/player/PlayerScreen.kt index 73b32c58bb..d5fa14f516 100644 --- a/media/ui/src/main/java/com/google/android/horologist/media/ui/screens/player/PlayerScreen.kt +++ b/media/ui/src/main/java/com/google/android/horologist/media/ui/screens/player/PlayerScreen.kt @@ -153,6 +153,8 @@ public fun PlayerScreen( val endGuideline = createGuidelineFromEnd(0.0938f) val topGuideline = createGuidelineFromTop(0.12f) val bottomGuideline = createGuidelineFromBottom(0.063f) + val bottomSectionStartGuideline = createGuidelineFromStart(0.1248f) + val bottomSectionEndGuideline = createGuidelineFromEnd(0.1248f) Box( modifier = Modifier.constrainAs(topSection) { @@ -187,8 +189,8 @@ public fun PlayerScreen( modifier = Modifier .constrainAs(bottomSection) { top.linkTo(middleSection.bottom) - start.linkTo(startGuideline) - end.linkTo(endGuideline) + start.linkTo(bottomSectionStartGuideline) + end.linkTo(bottomSectionEndGuideline) bottom.linkTo(bottomGuideline) width = Dimension.fillToConstraints height = Dimension.fillToConstraints