Add Micro Book Thumbnail.
This commit is contained in:
parent
fb1709125d
commit
c7dc9b227c
5 changed files with 226 additions and 4 deletions
|
|
@ -0,0 +1,207 @@
|
||||||
|
package com.pixelized.biblib.ui.screen.home.common.item
|
||||||
|
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.wrapContentHeight
|
||||||
|
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.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
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 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.skydoves.landscapist.glide.GlideImage
|
||||||
|
|
||||||
|
@Stable
|
||||||
|
data class MicroBookThumbnailUio(
|
||||||
|
val id: Int,
|
||||||
|
val title: String,
|
||||||
|
val author: String,
|
||||||
|
val isNew: Boolean,
|
||||||
|
val cover: String,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MicroBookThumbnail(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
thumbnail: MicroBookThumbnailUio?,
|
||||||
|
onClick: (MicroBookThumbnailUio) -> Unit = default<MicroBookThumbnailUio>(),
|
||||||
|
) {
|
||||||
|
if (thumbnail != null) {
|
||||||
|
MicroBookThumbnailContent(
|
||||||
|
modifier = modifier,
|
||||||
|
thumbnail = thumbnail,
|
||||||
|
onClick = onClick,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
MicroBookThumbnailPlaceHolder(
|
||||||
|
modifier = modifier,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MicroBookThumbnailContent(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
thumbnail: MicroBookThumbnailUio,
|
||||||
|
onClick: (MicroBookThumbnailUio) -> Unit = default<MicroBookThumbnailUio>(),
|
||||||
|
) {
|
||||||
|
val dimen = MaterialTheme.bibLib.dimen
|
||||||
|
Card(
|
||||||
|
modifier = modifier
|
||||||
|
.clickable { onClick(thumbnail) }
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight(),
|
||||||
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
|
) {
|
||||||
|
ConstraintLayout(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
val (cover, title, author) = createRefs()
|
||||||
|
|
||||||
|
GlideImage(
|
||||||
|
modifier = Modifier
|
||||||
|
.constrainAs(cover) {
|
||||||
|
top.linkTo(parent.top)
|
||||||
|
bottom.linkTo(parent.bottom)
|
||||||
|
start.linkTo(parent.start)
|
||||||
|
}
|
||||||
|
.clip(shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall)
|
||||||
|
.size(size = MaterialTheme.bibLib.dimen.thumbnail.micro),
|
||||||
|
previewPlaceholder = R.drawable.ic_fondation_thumbnail,
|
||||||
|
imageModel = thumbnail.cover,
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.constrainAs(title) {
|
||||||
|
top.linkTo(parent.top, margin = dimen.dp8)
|
||||||
|
start.linkTo(cover.end, margin = dimen.dp8)
|
||||||
|
end.linkTo(parent.end, margin = dimen.dp8)
|
||||||
|
width = Dimension.fillToConstraints
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.body1,
|
||||||
|
color = MaterialTheme.bibLib.colors.typography.medium,
|
||||||
|
text = thumbnail.title,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
)
|
||||||
|
|
||||||
|
Text(
|
||||||
|
modifier = Modifier.constrainAs(author) {
|
||||||
|
top.linkTo(title.bottom, margin = dimen.dp4)
|
||||||
|
bottom.linkTo(parent.bottom, margin = dimen.dp4)
|
||||||
|
start.linkTo(cover.end, margin = dimen.dp8)
|
||||||
|
end.linkTo(parent.end, margin = dimen.dp8)
|
||||||
|
width = Dimension.fillToConstraints
|
||||||
|
height = Dimension.fillToConstraints
|
||||||
|
},
|
||||||
|
style = MaterialTheme.typography.caption,
|
||||||
|
color = MaterialTheme.bibLib.colors.typography.easy,
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
text = thumbnail.author
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun MicroBookThumbnailPlaceHolder(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
) {
|
||||||
|
val dimen = MaterialTheme.bibLib.dimen
|
||||||
|
Card(
|
||||||
|
modifier = modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.wrapContentHeight(),
|
||||||
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
|
) {
|
||||||
|
ConstraintLayout(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
val (cover, title, author) = createRefs()
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.constrainAs(cover) {
|
||||||
|
top.linkTo(parent.top)
|
||||||
|
bottom.linkTo(parent.bottom)
|
||||||
|
start.linkTo(parent.start)
|
||||||
|
}
|
||||||
|
.size(size = MaterialTheme.bibLib.dimen.thumbnail.micro)
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
|
shape = MaterialTheme.bibLib.shapes.bookThumbnailCoverSmall,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.constrainAs(title) {
|
||||||
|
top.linkTo(parent.top, margin = dimen.dp8)
|
||||||
|
start.linkTo(cover.end, margin = dimen.dp8)
|
||||||
|
}
|
||||||
|
.size(width = 120.dp, height = 16.dp)
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
|
shape = CircleShape,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.constrainAs(author) {
|
||||||
|
top.linkTo(title.bottom, margin = dimen.dp4)
|
||||||
|
start.linkTo(cover.end, margin = dimen.dp8)
|
||||||
|
}
|
||||||
|
.size(width = 100.dp, height = 16.dp)
|
||||||
|
.background(
|
||||||
|
color = MaterialTheme.bibLib.colors.placeHolder,
|
||||||
|
shape = CircleShape,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
private fun MicroBookThumbnailPreview() {
|
||||||
|
BibLibTheme {
|
||||||
|
MicroBookThumbnail(
|
||||||
|
thumbnail = MicroBookThumbnailUio(
|
||||||
|
id = 0,
|
||||||
|
title = "Foundation",
|
||||||
|
author = "Asimov",
|
||||||
|
isNew = false,
|
||||||
|
cover = "",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
private fun MicroBookThumbnailEmptyPreview() {
|
||||||
|
BibLibTheme {
|
||||||
|
MicroBookThumbnail(
|
||||||
|
thumbnail = null,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,6 +34,8 @@ import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
||||||
import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel
|
import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel
|
||||||
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
||||||
|
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnail
|
||||||
|
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnail
|
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnail
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnailUio
|
||||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||||
|
|
@ -72,10 +74,10 @@ fun SearchPage(
|
||||||
@Composable
|
@Composable
|
||||||
private fun SearchPageContent(
|
private fun SearchPageContent(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
search: Flow<PagingData<SmallBookThumbnailUio>> = emptyFlow(),
|
search: Flow<PagingData<MicroBookThumbnailUio>> = emptyFlow(),
|
||||||
filters: List<SearchFilter> = SearchFilter.all,
|
filters: List<SearchFilter> = SearchFilter.all,
|
||||||
onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
|
onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
|
||||||
onDetail: (item: SmallBookThumbnailUio) -> Unit = default<SmallBookThumbnailUio>()
|
onDetail: (item: MicroBookThumbnailUio) -> Unit = default<MicroBookThumbnailUio>()
|
||||||
) {
|
) {
|
||||||
val items = search.collectAsLazyPagingItems()
|
val items = search.collectAsLazyPagingItems()
|
||||||
|
|
||||||
|
|
@ -96,7 +98,7 @@ private fun SearchPageContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
items(items = items, key = { it.id }) { item ->
|
items(items = items, key = { it.id }) { item ->
|
||||||
SmallBookThumbnail(
|
MicroBookThumbnail(
|
||||||
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
||||||
thumbnail = item,
|
thumbnail = item,
|
||||||
onClick = { onDetail(it) }
|
onClick = { onDetail(it) }
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import androidx.paging.*
|
import androidx.paging.*
|
||||||
import com.pixelized.biblib.repository.book.IBookRepository
|
import com.pixelized.biblib.repository.book.IBookRepository
|
||||||
|
import com.pixelized.biblib.utils.extention.toMicroThumbnailUio
|
||||||
import com.pixelized.biblib.utils.extention.toSmallThumbnailUio
|
import com.pixelized.biblib.utils.extention.toSmallThumbnailUio
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
|
@ -86,7 +87,7 @@ class SearchViewModel @Inject constructor(
|
||||||
.combine(language.confirmFlow) { paging, filter ->
|
.combine(language.confirmFlow) { paging, filter ->
|
||||||
paging.filter { filter == null || it.language == null || it.language.id == filter.id }
|
paging.filter { filter == null || it.language == null || it.language.id == filter.id }
|
||||||
}
|
}
|
||||||
.map { paging -> paging.map { it.toSmallThumbnailUio() } }
|
.map { paging -> paging.map { it.toMicroThumbnailUio() } }
|
||||||
|
|
||||||
data class FilterUio(
|
data class FilterUio(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ data class BibLibDimen(
|
||||||
val padding: Dp = 16.dp,
|
val padding: Dp = 16.dp,
|
||||||
val arrangement: Dp = 16.dp,
|
val arrangement: Dp = 16.dp,
|
||||||
val cover: DpSize = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6
|
val cover: DpSize = DpSize(width = 72.dp, height = 115.dp), // ratio 1.6
|
||||||
|
val micro: DpSize = DpSize(width = 40.dp, height = 64.dp), // ratio 1.6
|
||||||
)
|
)
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import androidx.annotation.StringDef
|
||||||
import com.pixelized.biblib.model.book.Book
|
import com.pixelized.biblib.model.book.Book
|
||||||
import com.pixelized.biblib.network.client.IBibLibClient
|
import com.pixelized.biblib.network.client.IBibLibClient
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnailUio
|
||||||
|
import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio
|
||||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnailUio
|
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnailUio
|
||||||
import com.pixelized.biblib.ui.screen.home.detail.BookDetailUio
|
import com.pixelized.biblib.ui.screen.home.detail.BookDetailUio
|
||||||
|
|
||||||
|
|
@ -15,6 +16,16 @@ import com.pixelized.biblib.ui.screen.home.detail.BookDetailUio
|
||||||
)
|
)
|
||||||
annotation class CoverUrl
|
annotation class CoverUrl
|
||||||
|
|
||||||
|
fun Book.toMicroThumbnailUio(
|
||||||
|
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
||||||
|
) = MicroBookThumbnailUio(
|
||||||
|
id = id,
|
||||||
|
title = title,
|
||||||
|
author = author.joinToString { it.name },
|
||||||
|
isNew = isNew,
|
||||||
|
cover = "${coverBaseUrl}/$id.jpg",
|
||||||
|
)
|
||||||
|
|
||||||
fun Book.toSmallThumbnailUio(
|
fun Book.toSmallThumbnailUio(
|
||||||
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
||||||
) = SmallBookThumbnailUio(
|
) = SmallBookThumbnailUio(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue