Skip to content

Commit

Permalink
Screenshot tests added for nothing and media playing screens
Browse files Browse the repository at this point in the history
  • Loading branch information
rajat4064g committed Oct 1, 2024
1 parent 46efae6 commit e54fb59
Show file tree
Hide file tree
Showing 44 changed files with 357 additions and 256 deletions.
2 changes: 2 additions & 0 deletions composables/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ package com.google.android.horologist.composables {
}

public final class MarqueeTextKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MarqueeText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional long color, optional androidx.compose.ui.text.TextStyle style, optional int textAlign, optional float followGap, optional float startEdgeGradientWidth, optional float endEdgeGradientWidth, optional float marqueeDpPerSecond, optional long pauseTime);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MarqueeText(androidx.compose.ui.text.AnnotatedString text, optional androidx.compose.ui.Modifier modifier, optional java.util.Map<java.lang.String,androidx.compose.foundation.text.InlineTextContent> inlineContent, optional long color, optional androidx.compose.ui.text.TextStyle style, optional int textAlign, optional float followGap, optional float edgeGradientWidth, optional float marqueeDpPerSecond, optional long pauseTime);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MarqueeText(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional androidx.compose.ui.text.TextStyle style, optional int textAlign, optional float followGap, optional float startEdgeGradientWidth, optional float endEdgeGradientWidth, optional float marqueeDpPerSecond, optional long pauseTime);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MarqueeText(String text, optional androidx.compose.ui.Modifier modifier, optional long color, optional androidx.compose.ui.text.TextStyle style, optional int textAlign, optional float followGap, optional float edgeGradientWidth, optional float marqueeDpPerSecond, optional long pauseTime);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.MarqueeSpacing
import androidx.compose.foundation.basicMarquee
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.InlineTextContent
import androidx.compose.runtime.Composable
Expand Down Expand Up @@ -75,7 +74,9 @@ import kotlin.time.Duration.Companion.seconds
* @param textAlign The alignment of the text within the lines of the paragraph.
* See [TextStyle.textAlign].
* @param followGap the width between end of each scrolling text and the start of the following one.
* @param edgeGradientWidth the width of the fade out zone on the edges, so text isn't cut off
* @param startEdgeGradientWidth the width of the fade out zone on the start edge, so text isn't cut
* off harshly.
* @param endEdgeGradientWidth the width of the fade out zone on the end edge, so text isn't cut off
* harshly.
* @param marqueeDpPerSecond the speed of scrolling in dp per second.
* @param pauseTime the duration before initially scrolling and each additional scroll.
Expand All @@ -90,12 +91,14 @@ public fun MarqueeText(
style: TextStyle = LocalTextStyle.current,
textAlign: TextAlign = TextAlign.Left,
followGap: Dp = 96.dp,
edgeGradientWidth: Dp = 16.dp,
startEdgeGradientWidth: Dp = 16.dp,
endEdgeGradientWidth: Dp = 16.dp,
marqueeDpPerSecond: Dp = 64.dp,
pauseTime: Duration = 4.seconds,
) {
val controller = remember(text, style) { MarqueeController(edgeGradientWidth) }
controller.edgeGradientWidth = edgeGradientWidth
val controller = remember(text, style) { MarqueeController(startEdgeGradientWidth, endEdgeGradientWidth) }
controller.startEdgeGradientWidth = startEdgeGradientWidth
controller.endEdgeGradientWidth = endEdgeGradientWidth

Text(
text = text,
Expand All @@ -118,6 +121,111 @@ public fun MarqueeText(
)
}

/**
* Show a single line Marquee text, with a pause (initial and between cycles) and speed.
*
* Otherwise is mostly the same as the [Text] composable, without params that don't apply for
* marquee, such as maxLines.
*
* Only scrolls if required, and otherwise uses textAlign to show the content in a
* stationary position.
*
* @param text The text to be displayed.
* @param modifier [Modifier] to apply to this layout node.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
* this will be [LocalContentColor].
* @param style Style configuration for the text such as color, font, line height etc.
* @param textAlign The alignment of the text within the lines of the paragraph.
* See [TextStyle.textAlign].
* @param followGap the width between end of each scrolling text and the start of the following one.
* @param startEdgeGradientWidth the width of the fade out zone on the start edge, so text isn't cut
* off harshly.
* @param endEdgeGradientWidth the width of the fade out zone on the end edge, so text isn't cut off
* harshly.
* @param marqueeDpPerSecond the speed of scrolling in dp per second.
* @param pauseTime the duration before initially scrolling and each additional scroll.
*/
@ExperimentalHorologistApi
@Composable
public fun MarqueeText(
text: String,
modifier: Modifier = Modifier,
color: Color = Color.Unspecified,
style: TextStyle = LocalTextStyle.current,
textAlign: TextAlign = TextAlign.Left,
followGap: Dp = 96.dp,
startEdgeGradientWidth: Dp = 16.dp,
endEdgeGradientWidth: Dp = 16.dp,
marqueeDpPerSecond: Dp = 64.dp,
pauseTime: Duration = 4.seconds,
) {
MarqueeText(
text = AnnotatedString(text),
inlineContent = emptyMap(),
modifier = modifier,
color = color,
style = style,
textAlign = textAlign,
followGap = followGap,
startEdgeGradientWidth = startEdgeGradientWidth,
endEdgeGradientWidth = endEdgeGradientWidth,
marqueeDpPerSecond = marqueeDpPerSecond,
pauseTime = pauseTime,
)
}

/**
* Show a single line Marquee text, with a pause (initial and between cycles) and speed.
*
* Otherwise is mostly the same as the [Text] composable, without params that don't apply for
* marquee, such as maxLines.
*
* Only scrolls if required, and otherwise uses textAlign to show the content in a
* stationary position.
*
* @param text The text to be displayed, where [AnnotatedString] allows multiple styles to be used.
* @param modifier [Modifier] to apply to this layout node.
* @param inlineContent A map store composables that replaces certain ranges of the text. It's
* used to insert composables into text layout. Check [InlineTextContent] for more information.
* @param color [Color] to apply to the text. If [Color.Unspecified], and [style] has no color set,
* this will be [LocalContentColor].
* @param style Style configuration for the text such as color, font, line height etc.
* @param textAlign The alignment of the text within the lines of the paragraph.
* See [TextStyle.textAlign].
* @param followGap the width between end of each scrolling text and the start of the following one.
* @param edgeGradientWidth the width of the fade out zone on the edges, so text isn't cut off
* harshly.
* @param marqueeDpPerSecond the speed of scrolling in dp per second.
* @param pauseTime the duration before initially scrolling and each additional scroll.
*/
@ExperimentalHorologistApi
@Composable
public fun MarqueeText(
text: AnnotatedString,
modifier: Modifier = Modifier,
inlineContent: Map<String, InlineTextContent> = mapOf(),
color: Color = Color.Unspecified,
style: TextStyle = LocalTextStyle.current,
textAlign: TextAlign = TextAlign.Left,
followGap: Dp = 96.dp,
edgeGradientWidth: Dp = 16.dp,
marqueeDpPerSecond: Dp = 64.dp,
pauseTime: Duration = 4.seconds,
) {
MarqueeText(
text = text,
inlineContent = inlineContent,
modifier = modifier,
color = color,
style = style,
textAlign = textAlign,
followGap = followGap,
startEdgeGradientWidth = edgeGradientWidth,
marqueeDpPerSecond = marqueeDpPerSecond,
pauseTime = pauseTime,
)
}

/**
* Show a single line Marquee text, with a pause (initial and between cycles) and speed.
*
Expand Down Expand Up @@ -167,9 +275,13 @@ public fun MarqueeText(
)
}

private class MarqueeController(edgeGradientWidth: Dp) {
private class MarqueeController(
startEdgeGradientWidth: Dp,
endEdgeGradientWidth: Dp,
) {

var edgeGradientWidth: Dp by mutableStateOf(edgeGradientWidth)
var startEdgeGradientWidth: Dp by mutableStateOf(startEdgeGradientWidth)
var endEdgeGradientWidth: Dp by mutableStateOf(endEdgeGradientWidth)
private var needsScrolling by mutableStateOf(false)
private var contentWidth: Int by mutableStateOf(-1)

Expand Down Expand Up @@ -197,18 +309,21 @@ private class MarqueeController(edgeGradientWidth: Dp) {

private val padding = object : PaddingValues {
override fun calculateLeftPadding(layoutDirection: LayoutDirection): Dp =
if (needsScrolling && layoutDirection == LayoutDirection.Ltr) edgeGradientWidth else 0.dp
if (layoutDirection == LayoutDirection.Ltr) startEdgeGradientWidth else 0.dp

override fun calculateRightPadding(layoutDirection: LayoutDirection): Dp =
if (needsScrolling && layoutDirection != LayoutDirection.Ltr) edgeGradientWidth else 0.dp
if (layoutDirection != LayoutDirection.Ltr) startEdgeGradientWidth else 0.dp

override fun calculateTopPadding(): Dp = 0.dp
override fun calculateBottomPadding(): Dp = 0.dp
}
val insideMarqueeModifier: Modifier = Modifier.padding(padding)

private fun Modifier.drawFadeGradient() = this.drawWithCache {
val width = edgeGradientWidth.toPx()
val leftWidth =
if (layoutDirection == LayoutDirection.Ltr) startEdgeGradientWidth.toPx() else endEdgeGradientWidth.toPx()
val rightWidth =
if (layoutDirection == LayoutDirection.Ltr) endEdgeGradientWidth.toPx() else startEdgeGradientWidth.toPx()
// Create the brush here and leverage it within the onDrawWithContent block below
// The brush will only be instantiated on first render and if the size of the composable
// changes. Otherwise the same brush instance will be used.
Expand All @@ -218,22 +333,22 @@ private class MarqueeController(edgeGradientWidth: Dp) {
Color.Black,
),
startX = 0f,
endX = width,
endX = leftWidth,
)
val rightBrush = Brush.horizontalGradient(
listOf(
Color.Transparent,
Color.Black,
),
startX = size.width,
endX = size.width - width,
endX = size.width - rightWidth,
)
onDrawWithContent {
drawContent()

if (needsScrolling) {
drawRect(
size = Size(width, size.height),
size = Size(leftWidth, size.height),
topLeft = Offset(
0f,
0f,
Expand All @@ -242,9 +357,9 @@ private class MarqueeController(edgeGradientWidth: Dp) {
blendMode = BlendMode.DstIn,
)
drawRect(
size = Size(width, size.height),
size = Size(rightWidth, size.height),
topLeft = Offset(
size.width - width,
size.width - rightWidth,
0f,
),
brush = rightBrush,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.wear.compose.material.MaterialTheme
import com.google.android.horologist.audio.ui.VolumeViewModel
import com.google.android.horologist.audio.ui.components.toAudioOutputUi
import com.google.android.horologist.images.base.paintable.DrawableResPaintable
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.logo.R
import com.google.android.horologist.media.ui.components.PodcastControlButtons
import com.google.android.horologist.media.ui.components.animated.AnimatedMediaControlButtons
import com.google.android.horologist.media.ui.components.animated.AnimatedMediaInfoDisplay
Expand Down Expand Up @@ -75,6 +77,7 @@ fun UampMediaPlayerScreen(
AnimatedMediaInfoDisplay(
media = playerUiState.media,
loading = !playerUiState.connected || playerUiState.media is MediaUiModel.Loading,
appIcon = DrawableResPaintable(R.drawable.ic_horologist_monochrome),
)
} else {
DefaultMediaInfoDisplay(playerUiState)
Expand All @@ -85,7 +88,6 @@ fun UampMediaPlayerScreen(
volumeUiState = volumeUiState,
audioOutputUi = audioOutput.toAudioOutputUi(),
onVolumeClick = onVolumeClick,
enabled = state.connected && state.media != null,
)
},
controlButtons = { playerUiController, playerUiState ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,13 @@ 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 androidx.wear.compose.material.ButtonDefaults
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
import com.google.android.horologist.audio.ui.components.actions.SetAudioOutputButton
import com.google.android.horologist.logo.R

/**
* Settings buttons for the UAMP media app.
Expand All @@ -42,40 +37,21 @@ public fun UampSettingsButtons(
audioOutputUi: AudioOutputUi,
onVolumeClick: () -> Unit,
modifier: Modifier = Modifier,
enabled: Boolean = true,
) {
val configuration = LocalConfiguration.current
val verticalPadding = (configuration.screenWidthDp * VERTICAL_PADDING_SCREEN_PERCENTAGE).dp

Row(
modifier = modifier
.fillMaxSize()
.padding(vertical = verticalPadding),
modifier = modifier.fillMaxSize(),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center,
) {
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,
)

FavoriteButton(
modifier = Modifier.weight(1f),
)
}
}

private const val VERTICAL_PADDING_SCREEN_PERCENTAGE = 0.026f
Loading

0 comments on commit e54fb59

Please sign in to comment.