From 8fc9f1dfd2b8c8eadade5236a452a6c8b2664251 Mon Sep 17 00:00:00 2001 From: kmd-htsh Date: Mon, 8 Mar 2021 23:30:55 +0900 Subject: [PATCH 1/3] Implements FirstFeedItem. --- .../droidkaigi/feeder/feed/FirstFeedItem.kt | 178 ++++++++++++++++++ 1 file changed, 178 insertions(+) create mode 100644 uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FirstFeedItem.kt diff --git a/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FirstFeedItem.kt b/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FirstFeedItem.kt new file mode 100644 index 000000000..0ecb75e98 --- /dev/null +++ b/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FirstFeedItem.kt @@ -0,0 +1,178 @@ +package io.github.droidkaigi.feeder.feed + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.aspectRatio +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.wrapContentWidth +import androidx.compose.material.Icon +import androidx.compose.material.IconToggleButton +import androidx.compose.material.LocalContentAlpha +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.CompositionLocalProvider +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.semantics.semantics +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.constraintlayout.compose.ConstraintLayout +import androidx.constraintlayout.compose.Dimension +import io.github.droidkaigi.feeder.FeedItem +import io.github.droidkaigi.feeder.Media +import io.github.droidkaigi.feeder.core.NetworkImage +import io.github.droidkaigi.feeder.core.theme.ConferenceAppFeederTheme +import io.github.droidkaigi.feeder.core.theme.typography +import io.github.droidkaigi.feeder.fakeFeedContents + +@Composable +fun FirstFeedItem( + feedItem: FeedItem, + favorited: Boolean, + showMediaLabel: Boolean = false, + onClick: (FeedItem) -> Unit, + onFavoriteChange: (FeedItem) -> Unit, +) { + ConstraintLayout( + modifier = Modifier + .clickable( + onClick = { onClick(feedItem) } + ) + .fillMaxWidth() + .semantics(mergeDescendants = true) { } + ) { + val (image, title, media, date, favorite) = createRefs() + NetworkImage( + url = feedItem.image.standardUrl, + modifier = Modifier + .constrainAs(image) { + top.linkTo(parent.top) + start.linkTo(parent.start) + end.linkTo(parent.end) + } + .wrapContentWidth() + .aspectRatio(16F / 9F), + contentScale = ContentScale.Crop, + contentDescription = null + ) + Text( + modifier = Modifier.constrainAs(title) { + start.linkTo(parent.start, 20.dp) + top.linkTo(image.bottom, 20.dp) + end.linkTo(favorite.start, 20.dp) + width = Dimension.fillToConstraints + }, + text = feedItem.title.jaTitle, + style = typography.h5, + maxLines = 2, + overflow = TextOverflow.Ellipsis + ) + if (showMediaLabel) { + Text( + modifier = Modifier + .constrainAs(media) { + top.linkTo(title.bottom, 8.dp) + start.linkTo(parent.start, 20.dp) + bottom.linkTo(parent.bottom, 12.dp) + } + .background( + color = feedItem.media.color(), + shape = MaterialTheme.shapes.small + ) + .padding(vertical = 4.dp, horizontal = 8.dp), + text = feedItem.media.text, + color = Color.White + ) + } + CompositionLocalProvider(LocalContentAlpha provides 0.54f) { + Text( + modifier = Modifier.constrainAs(date) { + top.linkTo(title.bottom, 8.dp) + bottom.linkTo(parent.bottom, 12.dp) + if (showMediaLabel) { + start.linkTo(media.end, 12.dp) + } else { + start.linkTo(parent.start, 20.dp) + } + }, + text = feedItem.publishedDateString(), + style = typography.caption + ) + } + IconToggleButton( + checked = false, + modifier = Modifier.constrainAs(favorite) { + top.linkTo(image.bottom, 36.dp) + end.linkTo(parent.end, 20.dp) + }, + content = { + Icon( + painterResource( + if (favorited) { + R.drawable + .ic_baseline_favorite_24 + } else { + R.drawable + .ic_baseline_favorite_border_24 + } + ), + "favorite" + ) + }, + onCheckedChange = { + onFavoriteChange(feedItem) + } + ) + } +} + +@Composable +private fun Media.color() = when (this) { + Media.YouTube -> { + Color.Red + } + Media.Medium -> { + Color.DarkGray + } + Media.DroidKaigiFM -> { + MaterialTheme.colors.secondary + } + else -> { + Color.Gray + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewFirstFeedItem() { + ConferenceAppFeederTheme { + val feedItem = fakeFeedContents().feedItemContents[0] + FirstFeedItem( + feedItem = feedItem, + favorited = false, + showMediaLabel = false, + onClick = { }, + onFavoriteChange = { } + ) + } +} + +@Preview(showBackground = true) +@Composable +fun PreviewFirstFeedItemWithMedia() { + ConferenceAppFeederTheme { + val feedItem = fakeFeedContents().feedItemContents[0] + FirstFeedItem( + feedItem = feedItem, + favorited = false, + showMediaLabel = true, + onClick = { }, + onFavoriteChange = { } + ) + } +} From f29ce558247a1fec15fa4e05ee920f4b6d509a57 Mon Sep 17 00:00:00 2001 From: kmd-htsh Date: Mon, 8 Mar 2021 23:36:19 +0900 Subject: [PATCH 2/3] Fix to show FirstFeedItem when the first item on the Home tab. --- .../droidkaigi/feeder/feed/FeedScreen.kt | 41 +++++++++++++------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FeedScreen.kt b/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FeedScreen.kt index 59f3b47e6..4d088ed5e 100644 --- a/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FeedScreen.kt +++ b/uicomponent-compose/feed/src/main/java/io/github/droidkaigi/feeder/feed/FeedScreen.kt @@ -43,7 +43,11 @@ import kotlin.reflect.KClass sealed class FeedTabs(val name: String, val routePath: String) { object Home : FeedTabs("Home", "home") - sealed class FilteredFeed(val feedItemClass: KClass, name: String, routePath: String) : + sealed class FilteredFeed( + val feedItemClass: KClass, + name: String, + routePath: String, + ) : FeedTabs(name, routePath) { object Blog : FilteredFeed(FeedItem.Blog::class, "Blog", "blog") object Video : FilteredFeed(FeedItem.Video::class, "Video", "video") @@ -219,17 +223,30 @@ private fun FeedList( ) { if (feedContents.size > 0) { items(feedContents.contents.size * 2) { index -> - if (index % 2 == 0) { - Divider() - } else { - val (item, favorited) = feedContents.contents[index / 2] - FeedItem( - feedItem = item, - favorited = favorited, - onClick = onClickFeed, - showMediaLabel = isHome, - onFavoriteChange = onFavoriteChange - ) + when { + isHome && index == 0 -> { + val (item, favorited) = feedContents.contents[index] + FirstFeedItem( + feedItem = item, + favorited = favorited, + onClick = onClickFeed, + showMediaLabel = isHome, + onFavoriteChange = onFavoriteChange + ) + } + index % 2 == 1 -> { + Divider() + } + else -> { + val (item, favorited) = feedContents.contents[index / 2] + FeedItem( + feedItem = item, + favorited = favorited, + onClick = onClickFeed, + showMediaLabel = isHome, + onFavoriteChange = onFavoriteChange + ) + } } } } From 29db946fbbc1d4f5dd9741497ec31f5a29489a46 Mon Sep 17 00:00:00 2001 From: kmd-htsh Date: Tue, 9 Mar 2021 10:15:47 +0900 Subject: [PATCH 3/3] Fix to ':spotlessKotlinCheck' error. --- .idea/codeStyles/Project.xml | 9 +++++++++ .../java/io/github/droidkaigi/feeder/feed/FeedScreen.kt | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 691f78bad..f4c87a327 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -72,6 +72,15 @@ +