in Jetcaster/app/src/main/java/com/example/jetcaster/ui/home/category/PodcastCategory.kt [149:306]
fun EpisodeListItem(
episode: Episode,
podcast: Podcast,
onClick: (String) -> Unit,
modifier: Modifier = Modifier
) {
ConstraintLayout(modifier = modifier.clickable { onClick(episode.uri) }) {
val (
divider, episodeTitle, podcastTitle, image, playIcon,
date, addPlaylist, overflow
) = createRefs()
Divider(
Modifier.constrainAs(divider) {
top.linkTo(parent.top)
centerHorizontallyTo(parent)
width = fillToConstraints
}
)
// If we have an image Url, we can show it using Coil
Image(
painter = rememberImagePainter(
data = podcast.imageUrl,
builder = {
crossfade(true)
}
),
contentDescription = null,
contentScale = ContentScale.Crop,
modifier = Modifier
.size(56.dp)
.clip(MaterialTheme.shapes.medium)
.constrainAs(image) {
end.linkTo(parent.end, 16.dp)
top.linkTo(parent.top, 16.dp)
},
)
Text(
text = episode.title,
maxLines = 2,
style = MaterialTheme.typography.subtitle1,
modifier = Modifier.constrainAs(episodeTitle) {
linkTo(
start = parent.start,
end = image.start,
startMargin = Keyline1,
endMargin = 16.dp,
bias = 0f
)
top.linkTo(parent.top, 16.dp)
width = preferredWrapContent
}
)
val titleImageBarrier = createBottomBarrier(podcastTitle, image)
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Text(
text = podcast.title,
maxLines = 2,
style = MaterialTheme.typography.subtitle2,
modifier = Modifier.constrainAs(podcastTitle) {
linkTo(
start = parent.start,
end = image.start,
startMargin = Keyline1,
endMargin = 16.dp,
bias = 0f
)
top.linkTo(episodeTitle.bottom, 6.dp)
width = preferredWrapContent
}
)
}
Image(
imageVector = Icons.Rounded.PlayCircleFilled,
contentDescription = stringResource(R.string.cd_play),
contentScale = ContentScale.Fit,
colorFilter = ColorFilter.tint(LocalContentColor.current),
modifier = Modifier
.clickable(
interactionSource = remember { MutableInteractionSource() },
indication = rememberRipple(bounded = false, radius = 24.dp)
) { /* TODO */ }
.size(48.dp)
.padding(6.dp)
.semantics { role = Role.Button }
.constrainAs(playIcon) {
start.linkTo(parent.start, Keyline1)
top.linkTo(titleImageBarrier, margin = 10.dp)
bottom.linkTo(parent.bottom, 10.dp)
}
)
CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
Text(
text = when {
episode.duration != null -> {
// If we have the duration, we combine the date/duration via a
// formatted string
stringResource(
R.string.episode_date_duration,
MediumDateFormatter.format(episode.published),
episode.duration.toMinutes().toInt()
)
}
// Otherwise we just use the date
else -> MediumDateFormatter.format(episode.published)
},
maxLines = 1,
overflow = TextOverflow.Ellipsis,
style = MaterialTheme.typography.caption,
modifier = Modifier.constrainAs(date) {
centerVerticallyTo(playIcon)
linkTo(
start = playIcon.end,
startMargin = 12.dp,
end = addPlaylist.start,
endMargin = 16.dp,
bias = 0f // float this towards the start
)
}
)
IconButton(
onClick = { /* TODO */ },
modifier = Modifier.constrainAs(addPlaylist) {
end.linkTo(overflow.start)
centerVerticallyTo(playIcon)
}
) {
Icon(
imageVector = Icons.Default.PlaylistAdd,
contentDescription = stringResource(R.string.cd_add)
)
}
IconButton(
onClick = { /* TODO */ },
modifier = Modifier.constrainAs(overflow) {
end.linkTo(parent.end, 8.dp)
centerVerticallyTo(playIcon)
}
) {
Icon(
imageVector = Icons.Default.MoreVert,
contentDescription = stringResource(R.string.cd_more)
)
}
}
}
}