diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt new file mode 100644 index 0000000..fcdda2b --- /dev/null +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt @@ -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(), +) { + 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(), +) { + 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, + ) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt index cf153b6..fc1f147 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchPage.kt @@ -34,6 +34,8 @@ import com.pixelized.biblib.ui.scaffold.LocalCategorySearchBottomSheetState import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel 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.SmallBookThumbnailUio import com.pixelized.biblib.ui.theme.BibLibTheme @@ -72,10 +74,10 @@ fun SearchPage( @Composable private fun SearchPageContent( modifier: Modifier = Modifier, - search: Flow> = emptyFlow(), + search: Flow> = emptyFlow(), filters: List = SearchFilter.all, onFilter: (filter: SearchFilter) -> Unit = default(), - onDetail: (item: SmallBookThumbnailUio) -> Unit = default() + onDetail: (item: MicroBookThumbnailUio) -> Unit = default() ) { val items = search.collectAsLazyPagingItems() @@ -96,7 +98,7 @@ private fun SearchPageContent( ) } items(items = items, key = { it.id }) { item -> - SmallBookThumbnail( + MicroBookThumbnail( modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding), thumbnail = item, onClick = { onDetail(it) } diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchViewModel.kt index d52d52c..ce59652 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/SearchViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.repository.book.IBookRepository +import com.pixelized.biblib.utils.extention.toMicroThumbnailUio import com.pixelized.biblib.utils.extention.toSmallThumbnailUio import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.CoroutineScope @@ -86,7 +87,7 @@ class SearchViewModel @Inject constructor( .combine(language.confirmFlow) { paging, filter -> 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( val id: Int, diff --git a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt index 32a2828..ecb2e63 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt @@ -36,6 +36,7 @@ data class BibLibDimen( val padding: Dp = 16.dp, val arrangement: Dp = 16.dp, 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 diff --git a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt index aafe768..d7da39a 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt @@ -4,6 +4,7 @@ import androidx.annotation.StringDef import com.pixelized.biblib.model.book.Book 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.MicroBookThumbnailUio import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnailUio 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 +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( @CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL ) = SmallBookThumbnailUio(