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.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<PagingData<SmallBookThumbnailUio>> = emptyFlow(),
 | 
			
		||||
    search: Flow<PagingData<MicroBookThumbnailUio>> = emptyFlow(),
 | 
			
		||||
    filters: List<SearchFilter> = SearchFilter.all,
 | 
			
		||||
    onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
 | 
			
		||||
    onDetail: (item: SmallBookThumbnailUio) -> Unit = default<SmallBookThumbnailUio>()
 | 
			
		||||
    onDetail: (item: MicroBookThumbnailUio) -> Unit = default<MicroBookThumbnailUio>()
 | 
			
		||||
) {
 | 
			
		||||
    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) }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue