diff --git a/app/src/main/java/me/ash/reader/ui/component/base/RYAsyncImage.kt b/app/src/main/java/me/ash/reader/ui/component/base/RYAsyncImage.kt index cfd4959d7..d20c6d0ed 100644 --- a/app/src/main/java/me/ash/reader/ui/component/base/RYAsyncImage.kt +++ b/app/src/main/java/me/ash/reader/ui/component/base/RYAsyncImage.kt @@ -10,7 +10,12 @@ import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.drawscope.DrawScope import androidx.compose.ui.graphics.painter.Painter import androidx.compose.ui.layout.ContentScale +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import coil.compose.rememberAsyncImagePainter import coil.compose.rememberImagePainter +import coil.request.ImageRequest import coil.size.Precision import coil.size.Scale import coil.size.Size @@ -31,16 +36,15 @@ fun RYAsyncImage( @DrawableRes error: Int? = R.drawable.ic_broken_image_black_24dp, ) { Image( - painter = rememberImagePainter( - data = data, - builder = { + painter = rememberAsyncImagePainter( + ImageRequest.Builder(LocalContext.current).data(data = data).apply { if (placeholder != null) placeholder(placeholder) if (error != null) error(error) crossfade(true) scale(scale) precision(precision) size(size) - }, + }.build() ), contentDescription = contentDescription, contentScale = contentScale, diff --git a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt index c5c6b1295..aca0bc023 100644 --- a/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt +++ b/app/src/main/java/me/ash/reader/ui/page/home/flow/ArticleItem.kt @@ -32,7 +32,6 @@ import androidx.compose.material.icons.rounded.CheckCircleOutline import androidx.compose.material.icons.rounded.FiberManualRecord import androidx.compose.material.icons.rounded.Share import androidx.compose.material.icons.rounded.Star -import androidx.compose.material3.DropdownMenu import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.HorizontalDivider @@ -90,13 +89,46 @@ import me.ash.reader.ui.page.settings.color.flow.generateArticleWithFeedPreview import me.ash.reader.ui.theme.Shape20 import me.ash.reader.ui.theme.palette.onDark -@OptIn(ExperimentalFoundationApi::class) @Composable fun ArticleItem( modifier: Modifier = Modifier, articleWithFeed: ArticleWithFeed, onClick: (ArticleWithFeed) -> Unit = {}, onLongClick: (() -> Unit)? = null +) { + val feed = articleWithFeed.feed + val article = articleWithFeed.article + + ArticleItem( + modifier = modifier, + feedName = feed.name, + feedIconUrl = feed.icon, + title = article.title, + shortDescription = article.shortDescription, + dateString = article.dateString, + imgData = article.img, + isStarred = article.isStarred, + isUnread = article.isUnread, + onClick = { onClick(articleWithFeed) }, + onLongClick = onLongClick + ) + +} + +@OptIn(ExperimentalFoundationApi::class) +@Composable +fun ArticleItem( + modifier: Modifier = Modifier, + feedName: String = "", + feedIconUrl: String? = null, + title: String = "", + shortDescription: String = "", + dateString: String? = null, + imgData: Any? = null, + isStarred: Boolean = false, + isUnread: Boolean = false, + onClick: () -> Unit = {}, + onLongClick: (() -> Unit)? = null ) { val articleListFeedIcon = LocalFlowArticleListFeedIcon.current val articleListFeedName = LocalFlowArticleListFeedName.current @@ -110,11 +142,11 @@ fun ArticleItem( .padding(horizontal = 12.dp) .clip(Shape20) .combinedClickable( - onClick = { onClick(articleWithFeed) }, + onClick = onClick, onLongClick = onLongClick, ) .padding(horizontal = 12.dp, vertical = 12.dp) - .alpha(articleWithFeed.article.run { + .alpha( when (articleListReadIndicator) { FlowArticleReadIndicatorPreference.AllRead -> { if (isUnread) 1f else 0.5f @@ -124,7 +156,7 @@ fun ArticleItem( if (isUnread || isStarred) 1f else 0.5f } } - }), + ), ) { // Top Row( @@ -138,7 +170,7 @@ fun ArticleItem( modifier = Modifier .weight(1f) .padding(start = if (articleListFeedIcon.value) 30.dp else 0.dp), - text = articleWithFeed.feed.name, + text = feedName, color = MaterialTheme.colorScheme.tertiary, style = MaterialTheme.typography.labelMedium, maxLines = 1, @@ -155,7 +187,7 @@ fun ArticleItem( Spacer(Modifier.width(if (articleListFeedIcon.value) 30.dp else 0.dp)) } // Starred - if (articleWithFeed.article.isStarred) { + if (isStarred) { Icon( modifier = Modifier .size(14.dp) @@ -169,7 +201,7 @@ fun ArticleItem( // Date Text( modifier = Modifier, - text = articleWithFeed.article.dateString ?: "", + text = dateString ?: "", color = MaterialTheme.colorScheme.outlineVariant, style = MaterialTheme.typography.labelMedium, ) @@ -185,7 +217,7 @@ fun ArticleItem( ) { // Feed icon if (articleListFeedIcon.value) { - FeedIcon(articleWithFeed.feed.name, iconUrl = articleWithFeed.feed.icon) + FeedIcon(feedName, iconUrl = feedIconUrl) Spacer(modifier = Modifier.width(10.dp)) } @@ -196,7 +228,7 @@ fun ArticleItem( // Title Text( - text = articleWithFeed.article.title, + text = title, color = MaterialTheme.colorScheme.onSurface, style = MaterialTheme.typography.titleMedium, maxLines = if (articleListDesc.value) 2 else 4, @@ -204,10 +236,10 @@ fun ArticleItem( ) // Description - if (articleListDesc.value && articleWithFeed.article.shortDescription.isNotBlank()) { + if (articleListDesc.value && shortDescription.isNotBlank()) { Text( modifier = Modifier.padding(top = 4.dp), - text = articleWithFeed.article.shortDescription, + text = shortDescription, color = MaterialTheme.colorScheme.onSurfaceVariant, style = MaterialTheme.typography.bodySmall, maxLines = 2, @@ -217,13 +249,13 @@ fun ArticleItem( } // Image - if (articleWithFeed.article.img != null && articleListImage.value) { + if (imgData != null && articleListImage.value) { RYAsyncImage( modifier = Modifier .padding(start = 10.dp) .size(80.dp) .clip(Shape20), - data = articleWithFeed.article.img, + data = imgData, scale = Scale.FILL, precision = Precision.INEXACT, size = SIZE_1000, diff --git a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt index e76da1ada..073f5019e 100644 --- a/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt +++ b/app/src/main/java/me/ash/reader/ui/page/settings/color/flow/FlowPagePreview.kt @@ -16,7 +16,6 @@ import androidx.compose.material3.TopAppBar import androidx.compose.material3.TopAppBarDefaults import androidx.compose.runtime.* import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp @@ -27,6 +26,7 @@ import me.ash.reader.domain.model.feed.Feed import me.ash.reader.domain.model.general.Filter import me.ash.reader.infrastructure.preference.FlowArticleListTonalElevationPreference import me.ash.reader.infrastructure.preference.FlowTopBarTonalElevationPreference +import me.ash.reader.infrastructure.preference.LocalDarkTheme import me.ash.reader.ui.component.FilterBar import me.ash.reader.ui.component.base.FeedbackIconButton import me.ash.reader.ui.ext.surfaceColorAtElevation @@ -77,13 +77,31 @@ fun FlowPagePreview( tint = MaterialTheme.colorScheme.onSurface, ) {} }, colors = TopAppBarDefaults.smallTopAppBarColors( - containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation(topBarTonalElevation.value.dp), + containerColor = MaterialTheme.colorScheme.surfaceColorAtElevation( + topBarTonalElevation.value.dp + ), ) ) Spacer(modifier = Modifier.height(12.dp)) + + val preview = generateArticleWithFeedPreview() + val feed = preview.feed + val article = preview.article + ArticleItem( - articleWithFeed = generateArticleWithFeedPreview(), + modifier = Modifier, + feedName = feed.name, + feedIconUrl = feed.icon, + title = article.title, + shortDescription = article.shortDescription, + dateString = article.dateString, + imgData = R.drawable.animation, + isStarred = article.isStarred, + isUnread = article.isUnread, + onClick = {}, + onLongClick = null ) + Spacer(modifier = Modifier.height(12.dp)) FilterBar( filter = filter, @@ -111,7 +129,7 @@ fun generateArticleWithFeedPreview(): ArticleWithFeed = accountId = 0, date = Date(1654053729L), isStarred = true, - img = "https://images.unsplash.com/photo-1544716278-ca5e3f4abd8c?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1yZWxhdGVkfDJ8fHxlbnwwfHx8fA%3D%3D&auto=format&fit=crop&w=800&q=60" + img = null ), feed = Feed( id = "", diff --git a/app/src/main/res/drawable/animation.webp b/app/src/main/res/drawable/animation.webp new file mode 100644 index 000000000..bc9fc45a4 Binary files /dev/null and b/app/src/main/res/drawable/animation.webp differ