Fix some layout.
This commit is contained in:
parent
9a5cd11782
commit
f79445c12c
10 changed files with 121 additions and 60 deletions
|
|
@ -16,10 +16,10 @@ class BookRepository : IBookRepository {
|
|||
override fun getAll(): List<Book> =
|
||||
database.bookDao().getAll().map { it.toBook() }
|
||||
|
||||
override fun getNews(): DataSource.Factory<Int, Book> =
|
||||
override fun getNewsSource(): DataSource.Factory<Int, Book> =
|
||||
database.bookDao().getNews().map { it.toBook() }
|
||||
|
||||
override fun getBook(): DataSource.Factory<Int, Book> =
|
||||
override fun getBooksSource(): DataSource.Factory<Int, Book> =
|
||||
database.bookDao().getBook().map { it.toBook() }
|
||||
|
||||
override suspend fun update(data: List<Book>) {
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ interface IBookRepository {
|
|||
|
||||
fun getAll(): List<Book>
|
||||
|
||||
fun getNews(): DataSource.Factory<Int, Book>
|
||||
fun getNewsSource(): DataSource.Factory<Int, Book>
|
||||
|
||||
fun getBook(): DataSource.Factory<Int, Book>
|
||||
fun getBooksSource(): DataSource.Factory<Int, Book>
|
||||
|
||||
suspend fun update(data: List<Book>)
|
||||
}
|
||||
|
|
@ -3,10 +3,7 @@ package com.pixelized.biblib.ui.composable.items
|
|||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.NavigateNext
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -34,6 +31,18 @@ private val THUMBNAIL_HEIGHT: Dp = 96.dp
|
|||
|
||||
@Composable
|
||||
fun BookItem(
|
||||
thumbnail: BookThumbnailUio?,
|
||||
onClick: ((BookThumbnailUio) -> Unit)? = null,
|
||||
) {
|
||||
if (thumbnail != null) {
|
||||
FilledBookItem(thumbnail, onClick)
|
||||
} else {
|
||||
EmptyBookItem()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun FilledBookItem(
|
||||
thumbnail: BookThumbnailUio,
|
||||
onClick: ((BookThumbnailUio) -> Unit)? = null,
|
||||
) {
|
||||
|
|
@ -78,24 +87,12 @@ fun BookItem(
|
|||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Row(
|
||||
modifier = Modifier.weight(1f),
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
thumbnail.date?.let { date ->
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Text(
|
||||
modifier = Modifier.align(Alignment.End),
|
||||
style = typography.caption,
|
||||
text = thumbnail.genre,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier
|
||||
.widthIn(min = 4.dp)
|
||||
.weight(1f)
|
||||
)
|
||||
Text(
|
||||
style = typography.caption,
|
||||
text = thumbnail.date,
|
||||
text = date,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
|
|
@ -109,13 +106,61 @@ fun BookItem(
|
|||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EmptyBookItem() {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.wrapContentHeight(),
|
||||
elevation = 4.dp,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.height(THUMBNAIL_HEIGHT),
|
||||
) {
|
||||
|
||||
Placeholder(
|
||||
modifier = Modifier
|
||||
.size(THUMBNAIL_WIDTH, THUMBNAIL_HEIGHT)
|
||||
.clip(RoundedCornerShape(4.dp)),
|
||||
)
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.weight(1f)
|
||||
) {
|
||||
Placeholder(
|
||||
modifier = Modifier.size(200.dp, 24.dp)
|
||||
)
|
||||
Placeholder(
|
||||
modifier = Modifier
|
||||
.size(80.dp, 16.dp)
|
||||
.padding(top = 4.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
Placeholder(
|
||||
modifier = Modifier
|
||||
.size(60.dp, 14.dp)
|
||||
.align(Alignment.End)
|
||||
)
|
||||
}
|
||||
Icon(
|
||||
modifier = Modifier.align(Alignment.CenterVertically),
|
||||
imageVector = Icons.Default.NavigateNext, contentDescription = ""
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun Placeholder(modifier: Modifier) = Surface(modifier = modifier, elevation = 4.dp) {}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun BookItemLightPreview() {
|
||||
Bob[BitmapCache::class] = BitmapCache(LocalContext.current)
|
||||
BibLibTheme {
|
||||
val mock = BookThumbnailMock()
|
||||
BookItem(thumbnail = mock.bookThumbnail)
|
||||
FilledBookItem(thumbnail = mock.bookThumbnail)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -125,6 +170,22 @@ fun BookItemDarkPreview() {
|
|||
Bob[BitmapCache::class] = BitmapCache(LocalContext.current)
|
||||
BibLibTheme(darkTheme = true) {
|
||||
val mock = BookThumbnailMock()
|
||||
BookItem(thumbnail = mock.bookThumbnail)
|
||||
FilledBookItem(thumbnail = mock.bookThumbnail)
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun EmptyBookItemLightPreview() {
|
||||
BibLibTheme {
|
||||
EmptyBookItem()
|
||||
}
|
||||
}
|
||||
|
||||
@Preview
|
||||
@Composable
|
||||
fun EmptyBookItemDarkPreview() {
|
||||
BibLibTheme(darkTheme = true) {
|
||||
EmptyBookItem()
|
||||
}
|
||||
}
|
||||
|
|
@ -22,6 +22,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
|
|
@ -121,16 +122,14 @@ fun DetailPage(book: BookUio) {
|
|||
title = stringResource(id = R.string.detail_language),
|
||||
label = book.language,
|
||||
)
|
||||
book.date?.let {
|
||||
TitleLabel(
|
||||
title = stringResource(id = R.string.detail_release),
|
||||
label = book.date,
|
||||
label = it,
|
||||
)
|
||||
}
|
||||
}
|
||||
Row(modifier = Modifier.padding(bottom = 16.dp)) {
|
||||
TitleLabel(
|
||||
title = stringResource(id = R.string.detail_genre),
|
||||
label = book.genre,
|
||||
)
|
||||
TitleLabel(
|
||||
title = stringResource(id = R.string.detail_series),
|
||||
label = book.series ?: "-",
|
||||
|
|
@ -161,6 +160,7 @@ private fun RowScope.TitleLabel(
|
|||
)
|
||||
Text(
|
||||
style = typography.body1,
|
||||
textAlign = TextAlign.Center,
|
||||
text = label,
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ fun HomePage(
|
|||
|
||||
// https://issuetracker.google.com/issues/177245496
|
||||
val data: LazyPagingItems<BookThumbnailUio> = when (currentPage) {
|
||||
is Page.Home.New -> booksViewModel.books.collectAsLazyPagingItems()
|
||||
else -> booksViewModel.news.collectAsLazyPagingItems()
|
||||
is Page.Home.New -> booksViewModel.news.collectAsLazyPagingItems()
|
||||
else -> booksViewModel.books.collectAsLazyPagingItems()
|
||||
}
|
||||
|
||||
val lazyListState = rememberLazyListState()
|
||||
|
|
@ -45,7 +45,7 @@ fun HomePage(
|
|||
state = lazyListState,
|
||||
) {
|
||||
items(data) { thumbnail ->
|
||||
BookItem(thumbnail = thumbnail!!) { item ->
|
||||
BookItem(thumbnail) { item ->
|
||||
navigationViewModel.navigateTo(Page.Detail(item.id))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ data class BookThumbnailUio(
|
|||
val genre: String,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val date: String,
|
||||
val date: String?,
|
||||
val isNew: Boolean,
|
||||
) {
|
||||
val cover: URL = URL("${THUMBNAIL_URL}/$id.jpg")
|
||||
|
|
|
|||
|
|
@ -7,10 +7,9 @@ data class BookUio(
|
|||
val id: Int,
|
||||
val title: String,
|
||||
val author: String,
|
||||
val genre: String,
|
||||
val rating: Float,
|
||||
val language: String,
|
||||
val date: String,
|
||||
val date: String?,
|
||||
val series: String?,
|
||||
val description: String,
|
||||
) {
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ val Purple700 = Color(0xFF3700B3)
|
|||
val Teal200 = Color(0xFF03DAC5)
|
||||
|
||||
val Green600 = Color(0xFF43a047)
|
||||
val Green600L = Color(0XFF76d275)
|
||||
val Green600D = Color(0XFF00701a)
|
||||
val Green600L = Color(0xFF76d275)
|
||||
val Green600D = Color(0xFF00701a)
|
||||
|
|
@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope
|
|||
import androidx.paging.Pager
|
||||
import androidx.paging.PagingConfig
|
||||
import androidx.paging.PagingData
|
||||
import androidx.paging.PagingSource
|
||||
import com.pixelized.biblib.model.Book
|
||||
import com.pixelized.biblib.network.client.IBibLibClient
|
||||
import com.pixelized.biblib.network.factory.BookFactory
|
||||
|
|
@ -27,25 +28,26 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
private val client: IBibLibClient by inject()
|
||||
private val apiCache: IAPICacheRepository by inject()
|
||||
|
||||
private val formatter = SimpleDateFormat("MMMM yyyy", Locale.getDefault())
|
||||
private val formatter_long = SimpleDateFormat("MMMM yyyy", Locale.getDefault())
|
||||
private val formatter_short = SimpleDateFormat("MMM yyyy", Locale.getDefault())
|
||||
|
||||
private val _state = MutableLiveData<IBooksViewModel.State>(IBooksViewModel.State.Initial)
|
||||
override val state: LiveData<IBooksViewModel.State> get() = _state
|
||||
|
||||
private val bookSource
|
||||
get() = bookRepository.getBook()
|
||||
private val bookSource: () -> PagingSource<Int, BookThumbnailUio>
|
||||
get() = bookRepository.getBooksSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.Default)
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
|
||||
override val books: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = bookSource
|
||||
).flow
|
||||
|
||||
private val newsSource
|
||||
get() = bookRepository.getNews()
|
||||
private val newsSource: () -> PagingSource<Int, BookThumbnailUio>
|
||||
get() = bookRepository.getNewsSource()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.Default)
|
||||
.asPagingSourceFactory(Dispatchers.IO)
|
||||
|
||||
override val news: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
|
|
@ -107,7 +109,11 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
genre = genre?.joinToString { it.name } ?: "",
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
date = formatter.format(releaseDate).capitalize(Locale.getDefault()),
|
||||
date = if (releaseDate.time < 0) {
|
||||
null
|
||||
} else {
|
||||
formatter_long.format(releaseDate).capitalize(Locale.getDefault())
|
||||
},
|
||||
isNew = isNew,
|
||||
)
|
||||
|
||||
|
|
@ -115,10 +121,13 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
id = id,
|
||||
title = title,
|
||||
author = author.joinToString { it.name },
|
||||
genre = genre?.joinToString { it.name } ?: "",
|
||||
rating = rating?.toFloat() ?: 0.0f,
|
||||
language = language?.displayLanguage?.capitalize(Locale.getDefault()) ?: "",
|
||||
date = formatter.format(releaseDate).capitalize(Locale.getDefault()),
|
||||
date = if (releaseDate.time < 0) {
|
||||
null
|
||||
} else {
|
||||
formatter_short.format(releaseDate).capitalize(Locale.getDefault())
|
||||
},
|
||||
series = series?.name,
|
||||
description = synopsis ?: "",
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import com.pixelized.biblib.ui.data.BookUio
|
|||
class BookMock {
|
||||
val book: BookUio = BookUio(
|
||||
id = 90,
|
||||
genre = "Sci-Fi",
|
||||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
|
|
@ -19,7 +18,6 @@ class BookMock {
|
|||
112 to BookUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
|
|
@ -30,7 +28,6 @@ class BookMock {
|
|||
78 to BookUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
|
|
@ -41,7 +38,6 @@ class BookMock {
|
|||
90 to BookUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
|
|
@ -52,7 +48,6 @@ class BookMock {
|
|||
184 to BookUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
|
|
@ -63,7 +58,6 @@ class BookMock {
|
|||
185 to BookUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
|
|
@ -74,7 +68,6 @@ class BookMock {
|
|||
119 to BookUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
|
|
@ -85,7 +78,6 @@ class BookMock {
|
|||
163 to BookUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue