Repository: android/nowinandroid
File: core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt (Kotlin)

Code before:
                        topics = userNewsResource.followableTopics,
                        onTopicClick = onTopicClick,
                    )
                }
            }
        }
    }
}

@Composable
fun NewsResourceHeaderImage(
    headerImageUrl: String?,
) {
    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,
        error = {
                Image(
                    painter =
                    painterResource(DesignsystemR.drawable.ic_placeholder_default),
                    contentDescription = "placeholder image",
                )
        },
        loading = {
            Box(
                modifier = Modifier.size(180.dp),
                contentAlignment = Alignment.Center,
            ) {
                CircularProgressIndicator(
                    Modifier.size(80.dp),
                    color = MaterialTheme.colorScheme.tertiary,
                )
            }
        },
    )
}

@Composable
fun NewsResourceTitle(
    newsResourceTitle: String,
    modifier: Modifier = Modifier,
) {
    Text(newsResourceTitle, style = MaterialTheme.typography.headlineSmall, modifier = modifier)
}

@Composable

Review comment (suggestion):
```suggestion
                    painter = painterResource(DesignsystemR.drawable.ic_placeholder_default),
                    contentDescription = "placeholder image",
```

Code after:
                    NewsResourceTopics(
                        topics = userNewsResource.followableTopics,
                        onTopicClick = onTopicClick,
                    )
                }
            }
        }
    }
}

@Composable
fun NewsResourceHeaderImage(
    headerImageUrl: String?,
) {
    var isLoading by remember { mutableStateOf(true) }
    var isError by remember { mutableStateOf(false) }
    val imageLoader = rememberAsyncImagePainter(
        model = headerImageUrl,
        onState = { state ->
            isLoading = state is AsyncImagePainter.State.Loading
            isError = state is AsyncImagePainter.State.Error
        },
    )
    Box(
        modifier = Modifier
            .fillMaxWidth()
            .height(180.dp),
        contentAlignment = Alignment.Center,
    ) {
        if (isLoading) {
            // Display a progress bar while loading
            CircularProgressIndicator(
                modifier = Modifier
                    .align(Alignment.Center)
                    .size(80.dp),
                color = MaterialTheme.colorScheme.tertiary,
            )
        }

        Image(
            modifier = Modifier
                .fillMaxWidth()
                .height(180.dp),
            contentScale = ContentScale.Crop,
            painter = if (isError.not()) imageLoader else painterResource(drawable.ic_placeholder_default),
            // TODO b/226661685: Investigate using alt text of  image to populate content description
            contentDescription = null, // decorative image,
        )
    }
}