Add isNew ribbon
This commit is contained in:
parent
8be1ecc0a7
commit
74fed885d0
8 changed files with 190 additions and 124 deletions
|
@ -1,33 +1,32 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.default
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Stable
|
||||
data class LargeBookThumbnailUio(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val date: String?,
|
||||
val isNew: Boolean,
|
||||
val cover: String,
|
||||
)
|
||||
|
@ -64,98 +63,52 @@ private fun LargeBookThumbnailContent(
|
|||
thumbnail: LargeBookThumbnailUio,
|
||||
onClick: (LargeBookThumbnailUio) -> Unit = default<LargeBookThumbnailUio>(),
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.clickable { thumbnail.let(onClick) }
|
||||
) {
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge)
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f),
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
imageModel = thumbnail.cover,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8),
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||
text = thumbnail.title,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.dp8),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||
text = thumbnail.author
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.End)
|
||||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8)
|
||||
.padding(bottom = MaterialTheme.bibLib.dimen.dp8),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||
text = thumbnail.date ?: ""
|
||||
)
|
||||
}
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge)
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f)
|
||||
.isNew { thumbnail.isNew }
|
||||
.clickable { thumbnail.let(onClick) },
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
imageModel = thumbnail.cover,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LargeBookThumbnailPlaceHolder(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||
),
|
||||
)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverLarge,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8)
|
||||
.size(width = 80.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8)
|
||||
.size(width = 60.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(alignment = Alignment.End)
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.padding(horizontal = MaterialTheme.bibLib.dimen.dp8)
|
||||
.padding(bottom = MaterialTheme.bibLib.dimen.dp8)
|
||||
.size(width = 40.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
@SuppressLint("ComposableModifierFactory")
|
||||
@Composable
|
||||
private fun Modifier.isNew(
|
||||
isNew: () -> Boolean,
|
||||
) = if (isNew()) {
|
||||
val theme = MaterialTheme.bibLib
|
||||
val label: String = stringResource(id = R.string.list_is_new)
|
||||
val color: Color = Color.Red
|
||||
val style: TextStyle = remember {
|
||||
theme.typography.base.caption.copy(color = Color.White)
|
||||
}
|
||||
drawDiagonalLabel(
|
||||
text = label,
|
||||
color = color,
|
||||
style = style,
|
||||
labelTextRatio = 4f,
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
@ -167,10 +120,7 @@ private fun LargeBookThumbnailPreview() {
|
|||
modifier = Modifier.width(168.dp),
|
||||
thumbnail = LargeBookThumbnailUio(
|
||||
id = 0,
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "February 1951",
|
||||
isNew = false,
|
||||
isNew = true,
|
||||
cover = "",
|
||||
),
|
||||
)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
@ -13,17 +14,23 @@ import androidx.compose.material.MaterialTheme
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import androidx.constraintlayout.compose.ConstraintLayout
|
||||
import androidx.constraintlayout.compose.Dimension
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.default
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Stable
|
||||
|
@ -82,7 +89,8 @@ private fun MicroBookThumbnailContent(
|
|||
start.linkTo(parent.start)
|
||||
}
|
||||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.micro),
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.micro)
|
||||
.isNew { thumbnail.isNew },
|
||||
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||
imageModel = thumbnail.cover,
|
||||
)
|
||||
|
@ -191,6 +199,30 @@ private fun MicroBookThumbnailPlaceHolder(
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ComposableModifierFactory")
|
||||
@Composable
|
||||
private fun Modifier.isNew(
|
||||
isNew: () -> Boolean,
|
||||
) = if (isNew()) {
|
||||
val theme = MaterialTheme.bibLib
|
||||
val label: String = stringResource(id = R.string.list_is_new)
|
||||
val color: Color = Color.Red
|
||||
val style: TextStyle = remember {
|
||||
theme.typography.base.caption.copy(
|
||||
color = Color.White,
|
||||
fontSize = 8.sp,
|
||||
)
|
||||
}
|
||||
drawDiagonalLabel(
|
||||
text = label,
|
||||
color = color,
|
||||
style = style,
|
||||
labelTextRatio = 2f,
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
@ -203,7 +235,7 @@ private fun MicroBookThumbnailPreview() {
|
|||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
series = "Foundation - 1",
|
||||
isNew = false,
|
||||
isNew = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.item
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
|
@ -10,9 +11,13 @@ import androidx.compose.material.MaterialTheme
|
|||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Stable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.TextStyle
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
|
@ -22,6 +27,7 @@ import com.pixelized.biblib.R
|
|||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.default
|
||||
import com.pixelized.biblib.utils.extention.modifier.drawDiagonalLabel
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Stable
|
||||
|
@ -81,7 +87,8 @@ private fun SmallBookThumbnailContent(
|
|||
start.linkTo(parent.start)
|
||||
}
|
||||
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover),
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover)
|
||||
.isNew { thumbnail.isNew },
|
||||
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||
imageModel = thumbnail.cover,
|
||||
)
|
||||
|
@ -228,6 +235,27 @@ private fun SmallBookThumbnailPlaceHolder(
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressLint("ComposableModifierFactory")
|
||||
@Composable
|
||||
private fun Modifier.isNew(
|
||||
isNew: () -> Boolean,
|
||||
) = if (isNew()) {
|
||||
val theme = MaterialTheme.bibLib
|
||||
val label: String = stringResource(id = R.string.list_is_new)
|
||||
val color: Color = Color.Red
|
||||
val style: TextStyle = remember {
|
||||
theme.typography.base.caption.copy(color = Color.White)
|
||||
}
|
||||
drawDiagonalLabel(
|
||||
text = label,
|
||||
color = color,
|
||||
style = style,
|
||||
labelTextRatio = 2f,
|
||||
)
|
||||
} else {
|
||||
this
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
|
@ -240,7 +268,7 @@ private fun SmallBookThumbnailPreview() {
|
|||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
isNew = true,
|
||||
cover = "",
|
||||
)
|
||||
)
|
||||
|
|
|
@ -84,57 +84,36 @@ fun largeBookThumbnailPreviewResources(): LazyPagingItems<LargeBookThumbnailUio>
|
|||
val thumbnails = listOf(
|
||||
LargeBookThumbnailUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
LargeBookThumbnailUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
|
|
|
@ -3,9 +3,10 @@ package com.pixelized.biblib.ui.theme.typography
|
|||
import androidx.compose.material.Typography
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.Stable
|
||||
import java.time.format.TextStyle
|
||||
|
||||
@Stable
|
||||
@Immutable
|
||||
data class BibLibTypography(
|
||||
val base: Typography = Typography()
|
||||
val base: Typography = Typography(),
|
||||
)
|
|
@ -44,9 +44,6 @@ fun Book.toLargeBookThumbnailUio(
|
|||
@CoverUrl coverBaseUrl: String = IBibLibClient.COVER_URL
|
||||
) = LargeBookThumbnailUio(
|
||||
id = id,
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = "${coverBaseUrl}/$id.jpg",
|
||||
)
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
package com.pixelized.biblib.utils.extention.modifier
|
||||
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.composed
|
||||
import androidx.compose.ui.draw.clipToBounds
|
||||
import androidx.compose.ui.draw.drawWithContent
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.geometry.Rect
|
||||
import androidx.compose.ui.geometry.Size
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.drawscope.withTransform
|
||||
import androidx.compose.ui.text.*
|
||||
import kotlin.math.sqrt
|
||||
|
||||
@OptIn(ExperimentalTextApi::class)
|
||||
fun Modifier.drawDiagonalLabel(
|
||||
text: String,
|
||||
color: Color,
|
||||
style: TextStyle,
|
||||
labelTextRatio: Float,
|
||||
) = clipToBounds().composed(
|
||||
factory = {
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
val textLayoutResult: TextLayoutResult = remember {
|
||||
textMeasurer.measure(text = AnnotatedString(text), style = style)
|
||||
}
|
||||
drawWithContent {
|
||||
val canvasWidth = size.width
|
||||
|
||||
val textSize = textLayoutResult.size
|
||||
val textWidth = textSize.width
|
||||
val textHeight = textSize.height
|
||||
|
||||
val rectWidth = textWidth * labelTextRatio * 1.1f
|
||||
|
||||
val rect = Rect(
|
||||
offset = Offset(canvasWidth - rectWidth, 0f),
|
||||
size = Size(rectWidth, textHeight.toFloat())
|
||||
)
|
||||
|
||||
val sqrt = sqrt(rectWidth / 2f)
|
||||
val translatePos = sqrt * sqrt
|
||||
|
||||
drawContent()
|
||||
withTransform(
|
||||
transformBlock = {
|
||||
rotate(
|
||||
degrees = 45f,
|
||||
pivot = Offset(
|
||||
canvasWidth - rectWidth / 2,
|
||||
translatePos
|
||||
)
|
||||
)
|
||||
},
|
||||
drawBlock = {
|
||||
drawRect(
|
||||
color = color,
|
||||
topLeft = rect.topLeft,
|
||||
size = rect.size
|
||||
)
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = text,
|
||||
style = style,
|
||||
topLeft = Offset(
|
||||
rect.left + (rectWidth - textWidth) / 2f,
|
||||
rect.top + (rect.bottom - textHeight) / 2f
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -55,6 +55,8 @@
|
|||
<string name="authentication_password">Password</string>
|
||||
<string name="authentication_credential_remember">Remember my credential</string>
|
||||
|
||||
<string name="list_is_new" translatable="false">New</string>
|
||||
|
||||
<string name="detail_rating">Rating</string>
|
||||
<string name="detail_language">Language</string>
|
||||
<string name="detail_release">Release</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue