Change search UI and refactor some stuff.
This commit is contained in:
parent
182c2bda48
commit
20a7811602
25 changed files with 520 additions and 393 deletions
|
|
@ -91,6 +91,7 @@ dependencies {
|
|||
// Android Compose
|
||||
implementation "androidx.compose.ui:ui:1.2.0-rc02"
|
||||
implementation "androidx.compose.material:material:1.1.1"
|
||||
implementation "androidx.constraintlayout:constraintlayout-compose:1.0.1"
|
||||
implementation "androidx.compose.runtime:runtime-livedata:1.1.1"
|
||||
implementation "androidx.compose.ui:ui-tooling-preview:1.1.1"
|
||||
debugImplementation "androidx.compose.ui:ui-tooling:1.1.1"
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ import com.pixelized.biblib.R
|
|||
import com.pixelized.biblib.ui.composable.StateUio
|
||||
import com.pixelized.biblib.ui.screen.home.detail.BookDetailViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.detail.DetailScreen
|
||||
import com.pixelized.biblib.ui.screen.home.detail.BookUio
|
||||
import com.pixelized.biblib.ui.screen.home.detail.BookDetailUio
|
||||
import com.pixelized.biblib.utils.extention.showToast
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
|
|
@ -61,7 +61,7 @@ fun rememberDetailBottomSheetState(
|
|||
): DetailBottomSheetState {
|
||||
val context: Context = LocalContext.current
|
||||
val detail = rememberSaveable(scope, viewModel, bottomSheetState) {
|
||||
mutableStateOf<BookUio?>(null)
|
||||
mutableStateOf<BookDetailUio?>(null)
|
||||
}
|
||||
val controller = DetailBottomSheetState(
|
||||
context = context,
|
||||
|
|
@ -80,9 +80,9 @@ class DetailBottomSheetState constructor(
|
|||
private val viewModel: BookDetailViewModel,
|
||||
private val scope: CoroutineScope,
|
||||
val bottomSheetState: ModalBottomSheetState,
|
||||
bookDetail: MutableState<BookUio?>,
|
||||
bookDetail: MutableState<BookDetailUio?>,
|
||||
) {
|
||||
var bookDetail: BookUio? by bookDetail
|
||||
var bookDetail: BookDetailUio? by bookDetail
|
||||
private set
|
||||
|
||||
fun expandBookDetail(id: Int) {
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ import com.pixelized.biblib.R
|
|||
import com.pixelized.biblib.ui.composable.Search
|
||||
import com.pixelized.biblib.ui.scaffold.*
|
||||
import com.pixelized.biblib.ui.scaffold.SearchScaffoldState.ContentState
|
||||
import com.pixelized.biblib.ui.screen.connectivity.ConnectivityViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.common.composable.ConnectivityHeader
|
||||
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityViewModel
|
||||
import com.pixelized.biblib.ui.screen.home.common.connectivity.ConnectivityHeader
|
||||
import com.pixelized.biblib.ui.screen.home.page.Page
|
||||
import com.pixelized.biblib.ui.screen.home.page.books.BooksPage
|
||||
import com.pixelized.biblib.ui.screen.home.page.news.NewsPage
|
||||
|
|
|
|||
|
|
@ -1,13 +1,10 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.composable
|
||||
package com.pixelized.biblib.ui.screen.home.common.connectivity
|
||||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.expandVertically
|
||||
import androidx.compose.animation.shrinkVertically
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.sizeIn
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
|
|
@ -41,17 +38,19 @@ fun ConnectivityHeader(
|
|||
.sizeIn(minHeight = ButtonDefaults.MinHeight)
|
||||
.padding(
|
||||
horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding,
|
||||
vertical = MaterialTheme.bibLib.dimen.thumbnail.arrangement,
|
||||
vertical = MaterialTheme.bibLib.dimen.dp8,
|
||||
),
|
||||
horizontalArrangement = Arrangement.Center,
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(
|
||||
modifier = Modifier.padding(end = MaterialTheme.bibLib.dimen.dp8),
|
||||
modifier = Modifier.size(MaterialTheme.bibLib.dimen.dp16),
|
||||
imageVector = Icons.Default.CloudOff,
|
||||
tint = MaterialTheme.colors.onError,
|
||||
contentDescription = null
|
||||
)
|
||||
Text(
|
||||
modifier = Modifier.padding(start = MaterialTheme.bibLib.dimen.dp8),
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onError,
|
||||
text = stringResource(id = R.string.error_offline),
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package com.pixelized.biblib.ui.screen.connectivity
|
||||
package com.pixelized.biblib.ui.screen.home.common.connectivity
|
||||
|
||||
import androidx.compose.runtime.State
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
|
|
@ -0,0 +1,392 @@
|
|||
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.*
|
||||
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.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 BookThumbnailUio(
|
||||
val id: Int,
|
||||
val genre: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val date: String?,
|
||||
val isNew: Boolean,
|
||||
val cover: String,
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun SmallBookThumbnail(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio?,
|
||||
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
||||
) {
|
||||
if (thumbnail != null) {
|
||||
SmallBookThumbnailContent(
|
||||
modifier = modifier,
|
||||
thumbnail = thumbnail,
|
||||
onClick = onClick,
|
||||
)
|
||||
} else {
|
||||
SmallBookThumbnailPlaceHolder(
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SmallBookThumbnailContent(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio,
|
||||
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
||||
) {
|
||||
val dimen = MaterialTheme.bibLib.dimen
|
||||
Card(
|
||||
modifier = modifier
|
||||
.clickable { onClick(thumbnail) }
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
) {
|
||||
ConstraintLayout(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
val (cover, title, author, genre, date) = createRefs()
|
||||
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.constrainAs(cover) {
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
start.linkTo(parent.start)
|
||||
}
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover),
|
||||
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.h6,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.title,
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.constrainAs(author) {
|
||||
top.linkTo(title.bottom, margin = dimen.dp4)
|
||||
bottom.linkTo(genre.top, 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.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = thumbnail.author
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.constrainAs(genre) {
|
||||
bottom.linkTo(parent.bottom, margin = dimen.dp8)
|
||||
start.linkTo(cover.end, margin = dimen.dp8)
|
||||
end.linkTo(date.start, margin = dimen.dp8)
|
||||
width = Dimension.fillToConstraints
|
||||
},
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.genre
|
||||
)
|
||||
|
||||
Text(
|
||||
modifier = Modifier.constrainAs(date) {
|
||||
bottom.linkTo(parent.bottom, margin = dimen.dp8)
|
||||
end.linkTo(parent.end, margin = dimen.dp8)
|
||||
},
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.date ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SmallBookThumbnailPlaceHolder(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
val dimen = MaterialTheme.bibLib.dimen
|
||||
Card(
|
||||
modifier = modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
) {
|
||||
ConstraintLayout(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
) {
|
||||
val (cover, title, author, genre, date) = createRefs()
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.constrainAs(cover) {
|
||||
top.linkTo(parent.top)
|
||||
bottom.linkTo(parent.bottom)
|
||||
start.linkTo(parent.start)
|
||||
}
|
||||
.size(size = MaterialTheme.bibLib.dimen.thumbnail.cover)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
),
|
||||
)
|
||||
|
||||
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.color.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.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.constrainAs(genre) {
|
||||
bottom.linkTo(parent.bottom, margin = dimen.dp8)
|
||||
start.linkTo(cover.end, margin = dimen.dp8)
|
||||
}
|
||||
.size(width = 80.dp, height = 16.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.constrainAs(date) {
|
||||
bottom.linkTo(parent.bottom, margin = dimen.dp8)
|
||||
end.linkTo(parent.end, margin = dimen.dp8)
|
||||
}
|
||||
.size(width = 40.dp, height = 16.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LargeBookThumbnail(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio?,
|
||||
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
||||
) {
|
||||
if (thumbnail != null) {
|
||||
LargeBookThumbnailContent(
|
||||
modifier = modifier,
|
||||
thumbnail = thumbnail,
|
||||
onClick = onClick,
|
||||
)
|
||||
} else {
|
||||
LargeBookThumbnailPlaceHolder(
|
||||
modifier = modifier,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LargeBookThumbnailContent(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio,
|
||||
onClick: (BookThumbnailUio) -> Unit = default<BookThumbnailUio>(),
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.clickable { thumbnail.let(onClick) }
|
||||
) {
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f),
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
imageModel = thumbnail.cover,
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.title,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.author
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail.date ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LargeBookThumbnailPlaceHolder(
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Column(modifier = modifier) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.aspectRatio(64f / 102f)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.size(width = 80.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.size(width = 60.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.padding(top = MaterialTheme.bibLib.dimen.dp4)
|
||||
.size(width = 40.dp, height = 12.dp)
|
||||
.background(
|
||||
color = MaterialTheme.bibLib.color.placeHolder,
|
||||
shape = CircleShape,
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun SmallBookThumbnailPreview() {
|
||||
BibLibTheme {
|
||||
SmallBookThumbnail(
|
||||
thumbnail = BookThumbnailUio(
|
||||
id = 0,
|
||||
genre = "Sci-Fi",
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun SmallBookThumbnailEmptyPreview() {
|
||||
BibLibTheme {
|
||||
SmallBookThumbnail(
|
||||
thumbnail = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun LargeBookThumbnailPreview() {
|
||||
BibLibTheme {
|
||||
LargeBookThumbnail(
|
||||
modifier = Modifier.width(168.dp),
|
||||
thumbnail = BookThumbnailUio(
|
||||
id = 0,
|
||||
genre = "Sci-Fi",
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun LargeBookThumbnailEmptyPreview() {
|
||||
BibLibTheme {
|
||||
LargeBookThumbnail(
|
||||
modifier = Modifier.width(168.dp),
|
||||
thumbnail = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.composable
|
||||
package com.pixelized.biblib.ui.screen.home.common.preview
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.common.uio
|
||||
|
||||
class BookThumbnailUio(
|
||||
val id: Int,
|
||||
val genre: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val date: String?,
|
||||
val isNew: Boolean,
|
||||
val cover: String,
|
||||
)
|
||||
|
|
@ -2,12 +2,10 @@ package com.pixelized.biblib.ui.screen.home.detail
|
|||
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.network.factory.BookFactory
|
||||
import com.pixelized.biblib.ui.composable.StateUio
|
||||
import com.pixelized.biblib.utils.extention.capitalize
|
||||
import com.pixelized.biblib.utils.extention.shortDate
|
||||
import com.pixelized.biblib.utils.extention.toDetailUio
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
|
|
@ -18,7 +16,7 @@ class BookDetailViewModel @Inject constructor(
|
|||
private val client: IBibLibClient,
|
||||
) : ViewModel() {
|
||||
|
||||
suspend fun getDetail(id: Int): StateUio<BookUio> {
|
||||
suspend fun getDetail(id: Int): StateUio<BookDetailUio> {
|
||||
return withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val book = getBookDetail(id = id)
|
||||
|
|
@ -30,25 +28,10 @@ class BookDetailViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun getBookDetail(id: Int): BookUio {
|
||||
private suspend fun getBookDetail(id: Int): BookDetailUio {
|
||||
val factory = BookFactory()
|
||||
val response = client.service.detail(id)
|
||||
val book = factory.fromDetailResponseToBook(response)
|
||||
return book.toUio()
|
||||
}
|
||||
|
||||
private fun Book.toUio(): BookUio {
|
||||
|
||||
return BookUio(
|
||||
id = id,
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
rating = rating?.toFloat() ?: 0.0f,
|
||||
language = language?.displayLanguage?.capitalize() ?: "",
|
||||
date = releaseDate.shortDate(),
|
||||
series = series?.name,
|
||||
description = synopsis ?: "",
|
||||
cover = "${IBibLibClient.COVER_URL}/$id.jpg",
|
||||
)
|
||||
return book.toDetailUio()
|
||||
}
|
||||
}
|
||||
|
|
@ -1,15 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.detail
|
||||
|
||||
import java.io.Serializable
|
||||
|
||||
data class BookUio(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val rating: Float,
|
||||
val language: String,
|
||||
val date: String?,
|
||||
val series: String?,
|
||||
val description: String,
|
||||
val cover: String,
|
||||
) : Serializable
|
||||
|
|
@ -43,16 +43,29 @@ 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.CircularReveal
|
||||
import com.skydoves.landscapist.ShimmerParams
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.Serializable
|
||||
|
||||
@Stable
|
||||
data class BookDetailUio(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val rating: Float,
|
||||
val language: String,
|
||||
val date: String?,
|
||||
val series: String?,
|
||||
val description: String,
|
||||
val cover: String,
|
||||
) : Serializable
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
fun DetailScreen(
|
||||
detailState: DetailBottomSheetState = LocalDetailBottomSheetState.current,
|
||||
profileViewModel: ProfileViewModel = hiltViewModel(),
|
||||
detail: BookUio? = null,
|
||||
detail: BookDetailUio? = null,
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
val sheet = rememberModalBottomSheetState(
|
||||
|
|
@ -77,9 +90,6 @@ fun DetailScreen(
|
|||
.navigationBarsPadding()
|
||||
.padding(bottom = MaterialTheme.bibLib.dimen.dp16),
|
||||
emails = (user as StateUio.Success<UserUio>).value.amazonEmails,
|
||||
onAction = {
|
||||
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -109,7 +119,7 @@ fun DetailScreen(
|
|||
@Composable
|
||||
private fun DetailScreenContent(
|
||||
modifier: Modifier = Modifier,
|
||||
book: BookUio,
|
||||
book: BookDetailUio,
|
||||
onMobi: () -> Unit = default(),
|
||||
onEpub: () -> Unit = default(),
|
||||
onSend: () -> Unit = default(),
|
||||
|
|
@ -136,7 +146,7 @@ private fun DetailScreenContent(
|
|||
)
|
||||
}
|
||||
},
|
||||
previewPlaceholder = R.drawable.ic_launcher_foreground,
|
||||
previewPlaceholder = R.drawable.ic_fondatoin_cover,
|
||||
circularReveal = CircularReveal(duration = 1000),
|
||||
contentScale = ContentScale.FillHeight,
|
||||
imageModel = book.cover,
|
||||
|
|
@ -288,7 +298,7 @@ private fun TitleLabel(
|
|||
private fun DetailScreenSendContent(
|
||||
modifier: Modifier = Modifier,
|
||||
emails: List<String>,
|
||||
onAction: (email: String) -> Unit = default<String>(),
|
||||
onEmail: (email: String) -> Unit = default<String>(),
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.fillMaxWidth(),
|
||||
|
|
@ -306,7 +316,7 @@ private fun DetailScreenSendContent(
|
|||
items(items = emails) { email ->
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable(onClick = { onAction(email) })
|
||||
.clickable(onClick = { onEmail(email) })
|
||||
.height(height = MaterialTheme.bibLib.dimen.dp52)
|
||||
.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
|
@ -340,7 +350,7 @@ private fun DetailScreenSendContent(
|
|||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun DetailScreenContentPreview() {
|
||||
val book = BookUio(
|
||||
val book = BookDetailUio(
|
||||
id = 90,
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
|
|
|
|||
|
|
@ -1,107 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.books
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import com.pixelized.biblib.R
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
|
||||
@Composable
|
||||
fun BookThumbnail(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio?,
|
||||
onClick: (BookThumbnailUio) -> Unit = { },
|
||||
) {
|
||||
val currentOnClick by rememberUpdatedState(newValue = onClick)
|
||||
Card(
|
||||
modifier = modifier
|
||||
.clickable(enabled = thumbnail != null) {
|
||||
thumbnail?.let { currentOnClick(it) }
|
||||
}
|
||||
.wrapContentHeight(),
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.height(MaterialTheme.bibLib.dimen.thumbnail.cover.height),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
thumbnail?.cover?.let { it ->
|
||||
GlideImage(
|
||||
modifier = Modifier.size(MaterialTheme.bibLib.dimen.thumbnail.cover),
|
||||
previewPlaceholder = R.drawable.ic_launcher_foreground,
|
||||
imageModel = it,
|
||||
)
|
||||
}
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(MaterialTheme.bibLib.dimen.dp8)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.padding(bottom = MaterialTheme.bibLib.dimen.dp4),
|
||||
style = MaterialTheme.typography.h6,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.title ?: "",
|
||||
maxLines = 2,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = thumbnail?.author ?: ""
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Row(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.genre ?: ""
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.date ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun BookThumbnailPreview() {
|
||||
val thumbnail = BookThumbnailUio(
|
||||
id = 0,
|
||||
genre = "Sci-Fi",
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
)
|
||||
BibLibTheme {
|
||||
BookThumbnail(thumbnail = thumbnail)
|
||||
}
|
||||
}
|
||||
|
|
@ -13,8 +13,9 @@ import androidx.hilt.navigation.compose.hiltViewModel
|
|||
import androidx.paging.compose.LazyPagingItems
|
||||
import androidx.paging.compose.items
|
||||
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
||||
import com.pixelized.biblib.ui.screen.home.common.composable.bookPreviewResources
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.preview.bookPreviewResources
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnail
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.navigationBarsHeight
|
||||
|
|
@ -48,7 +49,7 @@ private fun BooksPageContent(
|
|||
items = books,
|
||||
key = { it.id },
|
||||
) { thumbnail ->
|
||||
BookThumbnail(
|
||||
SmallBookThumbnail(
|
||||
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
||||
thumbnail = thumbnail,
|
||||
onClick = {
|
||||
|
|
|
|||
|
|
@ -8,8 +8,9 @@ import androidx.paging.compose.collectAsLazyPagingItems
|
|||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.utils.extention.longDate
|
||||
import com.pixelized.biblib.utils.extention.toThumbnailUio
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import javax.inject.Inject
|
||||
|
|
@ -23,22 +24,12 @@ class BooksViewModel @Inject constructor(
|
|||
private val booksSource = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getBooksSource()
|
||||
.map { it.toThumbnail() }
|
||||
.map { it.toThumbnailUio() }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
|
||||
val books @Composable get() = booksSource.collectAsLazyPagingItems()
|
||||
|
||||
private fun Book.toThumbnail() = BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = "${IBibLibClient.THUMBNAIL_URL}/$id.jpg"
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val PAGING_SIZE = 16
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.news
|
||||
|
||||
import android.content.res.Configuration
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.aspectRatio
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.width
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
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 com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.skydoves.landscapist.glide.GlideImage
|
||||
import com.pixelized.biblib.R
|
||||
|
||||
@Composable
|
||||
fun NewThumbnail(
|
||||
modifier: Modifier = Modifier,
|
||||
thumbnail: BookThumbnailUio?,
|
||||
onClick: (BookThumbnailUio) -> Unit = { },
|
||||
) {
|
||||
Column(
|
||||
modifier = modifier.clickable { thumbnail?.let(onClick) }
|
||||
) {
|
||||
thumbnail?.cover?.let { it ->
|
||||
GlideImage(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clip(MaterialTheme.bibLib.shape.base.medium)
|
||||
.aspectRatio(64f / 102f),
|
||||
previewPlaceholder = R.drawable.ic_baseline_auto_stories_24,
|
||||
imageModel = it,
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.title ?: "",
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.author ?: ""
|
||||
)
|
||||
|
||||
Text(
|
||||
style = MaterialTheme.typography.caption,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
text = thumbnail?.date ?: ""
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||
private fun BookThumbnailPreview() {
|
||||
val thumbnail = BookThumbnailUio(
|
||||
id = 0,
|
||||
genre = "Sci-Fi",
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
isNew = false,
|
||||
cover = "",
|
||||
)
|
||||
BibLibTheme {
|
||||
NewThumbnail(
|
||||
modifier = Modifier.width(200.dp),
|
||||
thumbnail = thumbnail,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -6,11 +6,10 @@ import androidx.paging.Pager
|
|||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.compose.collectAsLazyPagingItems
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.utils.extention.longDate
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.utils.extention.toThumbnailUio
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
|
@ -25,24 +24,12 @@ class NewsBookViewModel @Inject constructor(
|
|||
private val newsSource: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookRepository.getNewsSource()
|
||||
.map { it.toThumbnail() }
|
||||
.map { it.toThumbnailUio(coverBaseUrl = IBibLibClient.COVER_URL) }
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
).flow
|
||||
|
||||
val news @Composable get() = newsSource.collectAsLazyPagingItems()
|
||||
|
||||
private fun Book.toThumbnail(): BookThumbnailUio {
|
||||
return BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = "${IBibLibClient.COVER_URL}/$id.jpg"
|
||||
)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val PAGING_SIZE = 8
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,15 +7,14 @@ import androidx.compose.foundation.lazy.grid.GridCells
|
|||
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.hilt.navigation.compose.hiltViewModel
|
||||
import androidx.paging.compose.LazyPagingItems
|
||||
import com.pixelized.biblib.ui.scaffold.DetailBottomSheetState
|
||||
import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
||||
import com.pixelized.biblib.ui.screen.home.common.composable.bookPreviewResources
|
||||
import com.pixelized.biblib.ui.screen.home.common.uio.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.preview.bookPreviewResources
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.LargeBookThumbnail
|
||||
import com.pixelized.biblib.ui.theme.BibLibTheme
|
||||
import com.pixelized.biblib.utils.extention.bibLib
|
||||
import com.pixelized.biblib.utils.extention.navigationBarsHeight
|
||||
|
|
@ -52,7 +51,7 @@ private fun NewsPageContent(
|
|||
items(
|
||||
count = books.itemCount
|
||||
) { index ->
|
||||
NewThumbnail(
|
||||
LargeBookThumbnail(
|
||||
thumbnail = books[index],
|
||||
onClick = {
|
||||
detailBottomSheetState.expandBookDetail(id = it.id)
|
||||
|
|
@ -66,7 +65,6 @@ private fun NewsPageContent(
|
|||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun NewPagePreview() {
|
||||
val isNetworkAvailable = remember { mutableStateOf(false) }
|
||||
BibLibTheme {
|
||||
Column {
|
||||
NewsPageContent(
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
package com.pixelized.biblib.ui.screen.home.page.search
|
||||
|
||||
data class BookSearchUio(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val author: List<String>,
|
||||
val language: String? = null,
|
||||
val genre: List<String>? = null,
|
||||
val series: String? = null,
|
||||
)
|
||||
|
|
@ -2,11 +2,9 @@ package com.pixelized.biblib.ui.screen.home.page.search
|
|||
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_NO
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.Spring
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.spring
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
|
|
@ -14,13 +12,14 @@ import androidx.compose.foundation.rememberScrollState
|
|||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.ArrowDropDown
|
||||
import androidx.compose.material.icons.filled.NavigateNext
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.derivedStateOf
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.alpha
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.paging.LoadState
|
||||
import androidx.paging.PagingData
|
||||
|
|
@ -31,9 +30,12 @@ import com.pixelized.biblib.ui.scaffold.LocalDetailBottomSheetState
|
|||
import com.pixelized.biblib.ui.scaffold.LocalSearchBottomSheetState
|
||||
import com.pixelized.biblib.ui.scaffold.LocalSearchViewModel
|
||||
import com.pixelized.biblib.ui.scaffold.SearchFilter
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.SmallBookThumbnail
|
||||
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.navigationBarsHeight
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emptyFlow
|
||||
|
||||
|
|
@ -57,22 +59,16 @@ fun SearchPage(
|
|||
@Composable
|
||||
private fun SearchPageContent(
|
||||
modifier: Modifier = Modifier,
|
||||
search: Flow<PagingData<BookSearchUio>> = emptyFlow(),
|
||||
search: Flow<PagingData<BookThumbnailUio>> = emptyFlow(),
|
||||
filters: List<SearchFilter> = SearchFilter.all,
|
||||
onFilter: (filter: SearchFilter) -> Unit = default<SearchFilter>(),
|
||||
) {
|
||||
val items = search.collectAsLazyPagingItems()
|
||||
val detail = LocalDetailBottomSheetState.current
|
||||
|
||||
SearchLoader(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(MaterialTheme.bibLib.dimen.dp2),
|
||||
isLoading = { items.isLoading },
|
||||
)
|
||||
|
||||
LazyColumn(
|
||||
modifier = modifier,
|
||||
contentPadding = PaddingValues(bottom = MaterialTheme.bibLib.dimen.thumbnail.padding + navigationBarsHeight()),
|
||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.bibLib.dimen.dp8),
|
||||
) {
|
||||
item(key = "Search Filter") {
|
||||
|
|
@ -82,17 +78,21 @@ private fun SearchPageContent(
|
|||
onFilter = onFilter,
|
||||
)
|
||||
}
|
||||
items(items = items, key = { it.id }) {
|
||||
if (it != null) {
|
||||
SearchItem(
|
||||
item = it,
|
||||
onClick = {
|
||||
detail.expandBookDetail(it.id)
|
||||
}
|
||||
)
|
||||
}
|
||||
items(items = items, key = { it.id }) { item ->
|
||||
SmallBookThumbnail(
|
||||
modifier = Modifier.padding(horizontal = MaterialTheme.bibLib.dimen.thumbnail.padding),
|
||||
thumbnail = item,
|
||||
onClick = { item?.let { detail.expandBookDetail(it.id) } }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
SearchLoader(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.height(MaterialTheme.bibLib.dimen.dp2),
|
||||
isLoading = { items.isLoading },
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
|
|
@ -111,34 +111,6 @@ private fun SearchLoader(
|
|||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SearchItem(
|
||||
modifier: Modifier = Modifier,
|
||||
item: BookSearchUio,
|
||||
onClick: () -> Unit = default()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable(onClick = onClick)
|
||||
.fillMaxWidth()
|
||||
.padding(all = MaterialTheme.bibLib.dimen.dp16)
|
||||
.then(modifier)
|
||||
) {
|
||||
Text(
|
||||
modifier = Modifier.weight(1f),
|
||||
style = MaterialTheme.typography.body1,
|
||||
color = MaterialTheme.colors.onSurface,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
text = item.title
|
||||
)
|
||||
Icon(
|
||||
imageVector = Icons.Default.NavigateNext,
|
||||
contentDescription = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SearchFilter(
|
||||
modifier: Modifier = Modifier,
|
||||
|
|
@ -222,25 +194,6 @@ private val LazyPagingItems<*>.isLoading: Boolean
|
|||
return isLoading
|
||||
}
|
||||
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
|
||||
private fun SearchItemPreview() {
|
||||
BibLibTheme {
|
||||
SearchItem(
|
||||
item = BookSearchUio(
|
||||
id = 0,
|
||||
title = "Fondation",
|
||||
author = listOf("Issac Asimov"),
|
||||
language = "Fr",
|
||||
genre = listOf("SF, Classic"),
|
||||
series = "Fondation",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_NO)
|
||||
@Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ import androidx.lifecycle.ViewModel
|
|||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.paging.*
|
||||
import com.pixelized.biblib.model.book.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.repository.book.IBookRepository
|
||||
import com.pixelized.biblib.ui.screen.home.common.item.BookThumbnailUio
|
||||
import com.pixelized.biblib.utils.extention.longDate
|
||||
import com.pixelized.biblib.utils.extention.toThumbnailUio
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
|
@ -86,7 +90,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.toBookSearchUio() } }
|
||||
.map { paging -> paging.map { it.toThumbnailUio() } }
|
||||
|
||||
data class FilterUio(
|
||||
val id: Int,
|
||||
|
|
@ -129,16 +133,7 @@ class SearchViewModel @Inject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
private fun Book.toBookSearchUio() = BookSearchUio(
|
||||
id = id,
|
||||
title = title,
|
||||
author = author.map { it.name },
|
||||
language = language?.displayLanguage,
|
||||
genre = genre?.map { it.name },
|
||||
series = series?.name,
|
||||
)
|
||||
|
||||
companion object {
|
||||
private const val SEARCH_PAGE_SIZE = 15
|
||||
private const val SEARCH_PAGE_SIZE = 10
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,8 @@ import javax.annotation.concurrent.Immutable
|
|||
@Stable
|
||||
@Immutable
|
||||
data class BibLibColor(
|
||||
val base: Colors
|
||||
val base: Colors,
|
||||
val placeHolder: Color,
|
||||
)
|
||||
|
||||
fun bibLibDarkColors(
|
||||
|
|
@ -25,6 +26,7 @@ fun bibLibDarkColors(
|
|||
),
|
||||
) = BibLibColor(
|
||||
base = base,
|
||||
placeHolder = BibLibColorPalette.DarkGrey,
|
||||
)
|
||||
|
||||
fun bibLibLightColors(
|
||||
|
|
@ -38,4 +40,5 @@ fun bibLibLightColors(
|
|||
)
|
||||
) = BibLibColor(
|
||||
base = base,
|
||||
placeHolder = BibLibColorPalette.LightGrey,
|
||||
)
|
||||
|
|
@ -37,7 +37,7 @@ object BibLibColorPalette {
|
|||
val LightYellow: Color = Color(0xFFF5BF63)
|
||||
val VeryLightYellow: Color = Color(0xFFF9D679)
|
||||
val VeryDarkGrey: Color = Color(0xFF1D1D1D)
|
||||
val DarkGrey: Color = Color(0xFF727272)
|
||||
val DarkGrey: Color = Color(0xFF424242)
|
||||
val Grey: Color = Color(0xFF919195)
|
||||
val LightGrey: Color = Color(0xFFDFDFDF)
|
||||
val VeryLightGrey: Color = Color(0xFFF9F9F9)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
package com.pixelized.biblib.utils.extention
|
||||
|
||||
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.BookThumbnailUio
|
||||
import com.pixelized.biblib.ui.screen.home.detail.BookDetailUio
|
||||
|
||||
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@StringDef(
|
||||
IBibLibClient.THUMBNAIL_URL,
|
||||
IBibLibClient.COVER_URL,
|
||||
)
|
||||
annotation class CoverUrl
|
||||
|
||||
fun Book.toThumbnailUio(
|
||||
@CoverUrl coverBaseUrl: String = IBibLibClient.THUMBNAIL_URL
|
||||
) = BookThumbnailUio(
|
||||
id = id,
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = releaseDate.longDate(),
|
||||
isNew = isNew,
|
||||
cover = "${coverBaseUrl}/$id.jpg"
|
||||
)
|
||||
|
||||
fun Book.toDetailUio(
|
||||
@CoverUrl coverBaseUrl: String = IBibLibClient.COVER_URL
|
||||
) = BookDetailUio(
|
||||
id = id,
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
rating = rating?.toFloat() ?: 0.0f,
|
||||
language = language?.displayLanguage?.capitalize() ?: "",
|
||||
date = releaseDate.shortDate(),
|
||||
series = series?.name,
|
||||
description = synopsis ?: "",
|
||||
cover = "${coverBaseUrl}/$id.jpg",
|
||||
)
|
||||
BIN
app/src/main/res/drawable/ic_fondation_thumbnail.jpeg
Normal file
BIN
app/src/main/res/drawable/ic_fondation_thumbnail.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.9 KiB |
BIN
app/src/main/res/drawable/ic_fondatoin_cover.png
Normal file
BIN
app/src/main/res/drawable/ic_fondatoin_cover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 505 KiB |
Loading…
Add table
Add a link
Reference in a new issue