Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changes MediaUiModel to use Paintable #2176

Merged
merged 1 commit into from
Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion images/coil/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
package com.google.android.horologist.images.coil {

public final class ArtworkColorKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> rememberArtworkColor(String? artworkUri, optional long defaultColor);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Color> rememberArtworkColor(Object? model, optional long defaultColor);
}

@androidx.compose.runtime.Stable public final class CoilPaintable implements com.google.android.horologist.images.base.paintable.Paintable {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,19 @@ import com.google.android.horologist.annotations.ExperimentalHorologistApi
@Composable
@ExperimentalHorologistApi
public fun rememberArtworkColor(
artworkUri: String?,
model: Any?,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this a stability issue?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would this be better if we split into two APIs?

rememberArtworkColor(String?) and rememberArtworkColor(CoilDrawable)

defaultColor: Color = MaterialTheme.colors.primary,
): State<Color> {
val context = LocalContext.current
val imageLoader = context.imageLoader

val artworkColor = remember { mutableStateOf(defaultColor) }

LaunchedEffect(artworkUri) {
artworkColor.value = if (artworkUri != null) {
LaunchedEffect(model) {
artworkColor.value = if (model != null) {
val request =
ImageRequest.Builder(context)
.data(artworkUri)
.data(model)
.allowHardware(false)
.build()
val result = imageLoader.execute(request)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ import androidx.compose.ui.Modifier
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.wear.compose.material.MaterialTheme
import com.google.android.horologist.audio.ui.VolumeViewModel
import com.google.android.horologist.images.coil.CoilPaintable
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
import com.google.android.horologist.media.ui.components.background.ArtworkColorBackground
import com.google.android.horologist.media.ui.components.background.ColorBackground
import com.google.android.horologist.media.ui.screens.player.DefaultMediaInfoDisplay
import com.google.android.horologist.media.ui.screens.player.DefaultPlayerScreenControlButtons
import com.google.android.horologist.media.ui.screens.player.PlayerScreen
Expand All @@ -49,12 +51,19 @@ fun UampMediaPlayerScreen(
PlayerScreen(
modifier = modifier,
background = {
val artworkUri = it.media?.artworkUri
ArtworkColorBackground(
artworkUri = artworkUri,
defaultColor = MaterialTheme.colors.primary,
modifier = Modifier.fillMaxSize(),
)
val artworkColor = it.media?.artworkColor
if (artworkColor != null) {
ColorBackground(
color = artworkColor,
modifier = Modifier.fillMaxSize(),
)
} else {
ArtworkColorBackground(
paintable = it.media?.artwork as? CoilPaintable,
defaultColor = MaterialTheme.colors.primary,
modifier = Modifier.fillMaxSize(),
)
}
},
playerViewModel = mediaPlayerScreenViewModel,
volumeViewModel = volumeViewModel,
Expand Down
13 changes: 7 additions & 6 deletions media/ui/api/current.api
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ package com.google.android.horologist.media.ui.components {
}

public final class MediaArtworkKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MediaArtwork(androidx.compose.ui.graphics.painter.Painter painter, String? contentDescription, optional androidx.compose.ui.Modifier modifier);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MediaArtwork(com.google.android.horologist.images.base.paintable.Paintable artworkPaintable, String? contentDescription, optional androidx.compose.ui.Modifier modifier);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void MediaArtwork(com.google.android.horologist.media.ui.state.model.MediaUiModel media, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.painter.Painter? placeholder);
}
Expand Down Expand Up @@ -133,7 +134,7 @@ package com.google.android.horologist.media.ui.components.animated {
package com.google.android.horologist.media.ui.components.background {

public final class ArtworkColorBackgroundKt {
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ArtworkColorBackground(String? artworkUri, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Color? defaultColor, optional long background);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ArtworkColorBackground(com.google.android.horologist.images.coil.CoilPaintable? paintable, optional androidx.compose.ui.Modifier modifier, optional androidx.compose.ui.graphics.Color? defaultColor, optional long background);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static void ColorBackground(androidx.compose.ui.graphics.Color? color, optional androidx.compose.ui.Modifier modifier, optional long background);
method @androidx.compose.runtime.Composable @com.google.android.horologist.annotations.ExperimentalHorologistApi public static androidx.compose.runtime.State<androidx.compose.ui.graphics.Brush> rememberArtworkColorBrush(long artworkColor, optional long background);
}
Expand Down Expand Up @@ -769,23 +770,23 @@ package com.google.android.horologist.media.ui.state.model {
}

@com.google.android.horologist.annotations.ExperimentalHorologistApi public final class MediaUiModel {
ctor public MediaUiModel(String id, String title, optional String subtitle, optional String? artworkUri, optional androidx.compose.ui.graphics.Color? artworkColor, optional com.google.android.horologist.images.base.paintable.Paintable? titleIcon);
ctor public MediaUiModel(String id, String title, optional String subtitle, optional com.google.android.horologist.images.base.paintable.Paintable? artwork, optional androidx.compose.ui.graphics.Color? artworkColor, optional com.google.android.horologist.images.base.paintable.Paintable? titleIcon);
method public String component1();
method public String component2();
method public String component3();
method public String? component4();
method public com.google.android.horologist.images.base.paintable.Paintable? component4();
method public androidx.compose.ui.graphics.Color? component5-QN2ZGVo();
method public com.google.android.horologist.images.base.paintable.Paintable? component6();
method public com.google.android.horologist.media.ui.state.model.MediaUiModel copy-gCxFOHY(String id, String title, String subtitle, String? artworkUri, androidx.compose.ui.graphics.Color? artworkColor, com.google.android.horologist.images.base.paintable.Paintable? titleIcon);
method public com.google.android.horologist.media.ui.state.model.MediaUiModel copy-gCxFOHY(String id, String title, String subtitle, com.google.android.horologist.images.base.paintable.Paintable? artwork, androidx.compose.ui.graphics.Color? artworkColor, com.google.android.horologist.images.base.paintable.Paintable? titleIcon);
method public com.google.android.horologist.images.base.paintable.Paintable? getArtwork();
method public androidx.compose.ui.graphics.Color? getArtworkColor();
method public String? getArtworkUri();
method public String getId();
method public boolean getLoading();
method public String getSubtitle();
method public String getTitle();
method public com.google.android.horologist.images.base.paintable.Paintable? getTitleIcon();
property public final com.google.android.horologist.images.base.paintable.Paintable? artwork;
property public final androidx.compose.ui.graphics.Color? artworkColor;
property public final String? artworkUri;
property public final String id;
property public final boolean loading;
property public final String subtitle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ fun MediaArtworkPreview() {
media = MediaUiModel(
id = "id",
title = "title",
artworkUri = "artworkUri",
artwork = null,
),
placeholder = rememberVectorPainter(image = Icons.Default.Album),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ fun MediaChipPreview() {
media = MediaUiModel(
id = "id",
title = "Red Hot Chilli Peppers",
artworkUri = "artworkUri",
artwork = null,
),
onClick = {},
placeholder = rememberVectorPainter(
Expand Down Expand Up @@ -67,7 +67,7 @@ fun MediaChipPreviewNoArtwork() {
@Composable
fun MediaChipPreviewNoTitle() {
MediaChip(
media = MediaUiModel(id = "id", title = "title", artworkUri = "artworkUri"),
media = MediaUiModel(id = "id", title = "title", artwork = null),
onClick = {},
defaultTitle = "No title",
placeholder = rememberVectorPainter(
Expand All @@ -88,7 +88,7 @@ fun MediaChipPreviewVeryLongTitle() {
media = MediaUiModel(
id = "id",
title = "Very very very very very very very very very very very very very very very very very very very long title",
artworkUri = "artworkUri",
artwork = null,
),
onClick = {},
placeholder = rememberVectorPainter(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.layout.ContentScale
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.images.base.paintable.Paintable
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.media.ui.state.model.MediaUiModel

@ExperimentalHorologistApi
Expand All @@ -33,11 +32,14 @@ public fun MediaArtwork(
modifier: Modifier = Modifier,
placeholder: Painter? = null,
) {
MediaArtwork(
artworkPaintable = CoilPaintable(media.artworkUri, placeholder),
contentDescription = media.title,
modifier = modifier,
)
val painter = media.artwork?.rememberPainter() ?: placeholder
if (painter != null) {
MediaArtwork(
painter = painter,
contentDescription = media.title,
modifier = modifier,
)
}
}

@ExperimentalHorologistApi
Expand All @@ -54,3 +56,18 @@ public fun MediaArtwork(
contentScale = ContentScale.Fit,
)
}

@ExperimentalHorologistApi
@Composable
public fun MediaArtwork(
painter: Painter,
contentDescription: String?,
modifier: Modifier = Modifier,
) {
Image(
modifier = modifier,
painter = painter,
contentDescription = contentDescription,
contentScale = ContentScale.Fit,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ import com.google.android.horologist.media.ui.state.model.MediaUiModel
* A rounded chip to show a single [MediaUiModel].
*
* @param media The [MediaUiModel] that the [title][MediaUiModel.title] and
* [artwork][MediaUiModel.artworkUri] will be used to display on the chip.
* [artwork][MediaUiModel.artwork] will be used to display on the chip.
* @param onClick Will be called when the user clicks the chip.
* @param modifier The Modifier to be applied to the chip.
* @param defaultTitle A text to be used when [MediaUiModel.title] is null.
* @param placeholder A placeholder image to be displayed while
* [artwork][MediaUiModel.artworkUri] is being loaded.
* [artwork][MediaUiModel.artwork] is being loaded.
*/
@ExperimentalHorologistApi
@Composable
Expand All @@ -53,7 +53,7 @@ public fun MediaChip(
defaultTitle: String = "",
placeholder: Painter? = null,
) {
val artworkUri = media.artworkUri
val artworkUri = media.artwork
val title = media.title

MediaChip(
Expand All @@ -80,7 +80,7 @@ public fun MediaChip(
MediaArtwork(
modifier = Modifier.size(ChipDefaults.LargeIconSize),
contentDescription = title,
artworkPaintable = artworkPaintable,
artworkPaintable = it,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import androidx.compose.ui.graphics.RadialGradientShader
import androidx.compose.ui.graphics.compositeOver
import androidx.wear.compose.material.MaterialTheme
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.images.coil.rememberArtworkColor

/**
Expand All @@ -45,13 +46,13 @@ import com.google.android.horologist.images.coil.rememberArtworkColor
@Composable
@ExperimentalHorologistApi
public fun ArtworkColorBackground(
artworkUri: String?,
paintable: CoilPaintable?,
modifier: Modifier = Modifier,
defaultColor: Color? = null,
background: Color = MaterialTheme.colors.background,
) {
val artworkColor = rememberArtworkColor(
artworkUri = artworkUri,
model = paintable?.model,
defaultColor = defaultColor ?: Color.Black,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package com.google.android.horologist.media.ui.state.mapper

import androidx.compose.ui.graphics.Color
import com.google.android.horologist.annotations.ExperimentalHorologistApi
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.media.model.Media
import com.google.android.horologist.media.ui.state.model.MediaUiModel

Expand All @@ -38,7 +39,7 @@ public object MediaUiModelMapper {
id = media.id,
title = title,
subtitle = artist,
artworkUri = media.artworkUri,
artwork = media.artworkUri?.let { CoilPaintable(it) },
artworkColor = media.artworkColor?.let { Color(it) },
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public data class MediaUiModel(
val id: String,
val title: String,
val subtitle: String = "",
val artworkUri: String? = null,
val artwork: Paintable? = null,
val artworkColor: Color? = null,
val titleIcon: Paintable? = null,
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import coil.annotation.ExperimentalCoilApi
import coil.decode.DataSource
import coil.request.SuccessResult
import coil.test.FakeImageLoaderEngine
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.images.coil.FakeImageLoader
import com.google.android.horologist.media.ui.state.model.MediaUiModel
import com.google.android.horologist.screenshots.rng.WearLegacyA11yTest
Expand Down Expand Up @@ -62,7 +63,7 @@ class MediaArtworkA11yTest : WearLegacyA11yTest() {
media = MediaUiModel(
id = "id",
title = "title",
artworkUri = FakeImageLoader.TestIconResourceUri,
artwork = CoilPaintable(FakeImageLoader.TestIconResourceUri),
),
placeholder = rememberVectorPainter(image = Icons.Default.Album),
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import coil.annotation.ExperimentalCoilApi
import coil.decode.DataSource
import coil.request.SuccessResult
import coil.test.FakeImageLoaderEngine
import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.images.coil.FakeImageLoader
import com.google.android.horologist.media.ui.state.model.MediaUiModel
import com.google.android.horologist.screenshots.rng.WearLegacyA11yTest
Expand Down Expand Up @@ -55,7 +56,7 @@ class MediaChipA11yTest : WearLegacyA11yTest() {
media = MediaUiModel(
id = "id",
title = "Red Hot Chilli Peppers",
artworkUri = FakeImageLoader.TestIconResourceUri,
artwork = CoilPaintable(FakeImageLoader.TestIconResourceUri),
),
onClick = {},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package com.google.android.horologist.media.ui.state.mapper

import com.google.android.horologist.images.coil.CoilPaintable
import com.google.android.horologist.media.model.Media
import com.google.common.truth.Truth.assertThat
import org.junit.Test
Expand Down Expand Up @@ -44,6 +45,6 @@ class MediaUiModelMapperTest {
assertThat(result.id).isEqualTo(id)
assertThat(result.title).isEqualTo(title)
assertThat(result.subtitle).isEqualTo(artist)
assertThat(result.artworkUri).isEqualTo(artworkUri)
assertThat(result.artwork).isEqualTo(CoilPaintable(artworkUri))
}
}