diff --git a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt b/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt index e26a824af..abd783545 100644 --- a/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt +++ b/core/designsystem/src/main/java/com/google/samples/apps/nowinandroid/core/designsystem/component/DynamicAsyncImage.kt @@ -16,11 +16,19 @@ package com.google.samples.apps.nowinandroid.core.designsystem.component +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.size +import androidx.compose.material3.CircularProgressIndicator +import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.painter.Painter +import androidx.compose.ui.unit.dp import coil.compose.AsyncImage +import coil.compose.SubcomposeAsyncImage import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalTintTheme /** @@ -34,11 +42,30 @@ fun DynamicAsyncImage( placeholder: Painter? = null, ) { val iconTint = LocalTintTheme.current.iconTint - AsyncImage( - placeholder = placeholder, + SubcomposeAsyncImage( + error = { + if (placeholder != null) { + Image( + painter = placeholder, + contentDescription = "placeholder image", + ) + } + }, model = imageUrl, contentDescription = contentDescription, colorFilter = if (iconTint != null) ColorFilter.tint(iconTint) else null, modifier = modifier, - ) + loading = { + Box( + modifier = modifier, + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator( + Modifier.size(80.dp), + color = MaterialTheme.colorScheme.tertiary, + ) + } + }, + + ) } diff --git a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt index c9a327881..aed1871fa 100644 --- a/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt +++ b/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt @@ -17,6 +17,7 @@ package com.google.samples.apps.nowinandroid.core.ui import androidx.compose.foundation.Canvas +import androidx.compose.foundation.Image import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -31,6 +32,7 @@ import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -44,6 +46,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment +import androidx.compose.ui.Alignment.Companion import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale @@ -58,6 +61,8 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import coil.compose.AsyncImage +import coil.compose.AsyncImagePainter +import coil.compose.SubcomposeAsyncImage import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconToggleButton import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopicTag import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons @@ -70,7 +75,6 @@ import kotlinx.datetime.Instant import kotlinx.datetime.toJavaInstant import java.time.ZoneId import java.time.format.DateTimeFormatter -import java.time.format.FormatStyle import java.util.Locale import com.google.samples.apps.nowinandroid.core.designsystem.R as DesignsystemR @@ -147,20 +151,37 @@ fun NewsResourceCardExpanded( fun NewsResourceHeaderImage( headerImageUrl: String?, ) { - AsyncImage( - placeholder = if (LocalInspectionMode.current) { - painterResource(DesignsystemR.drawable.ic_placeholder_default) - } else { - // TODO b/228077205, show specific loading image visual - null - }, + + SubcomposeAsyncImage( modifier = Modifier .fillMaxWidth() .height(180.dp), contentScale = ContentScale.Crop, model = headerImageUrl, // TODO b/226661685: Investigate using alt text of image to populate content description - contentDescription = null, // decorative image + contentDescription = null, // decorative image, + error = { + if (LocalInspectionMode.current) { + Image( + painter = + painterResource(DesignsystemR.drawable.ic_placeholder_default), + contentDescription = "placeholder image", + ) + } else { + null + } + }, + loading = { + Box( + modifier = Modifier.size(180.dp), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator( + Modifier.size(80.dp), + color = MaterialTheme.colorScheme.tertiary, + ) + } + }, ) } @@ -231,11 +252,8 @@ fun dateFormatted(publishDate: Instant): String { } } - return DateTimeFormatter - .ofLocalizedDate(FormatStyle.MEDIUM) - .withLocale(Locale.getDefault()) - .withZone(zoneId) - .format(publishDate.toJavaInstant()) + return DateTimeFormatter.ofPattern("MMM d, yyyy") + .withZone(zoneId).format(publishDate.toJavaInstant()) } @Composable