Add back the detail page linked to the API.

This commit is contained in:
Thomas Andres Gomez 2021-05-14 14:10:12 +02:00
parent d2acbf8d18
commit 90d6c4bd65
6 changed files with 53 additions and 10 deletions

View file

@ -12,6 +12,8 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Send import androidx.compose.material.icons.filled.Send
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.clip
@ -23,16 +25,30 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import com.pixelized.biblib.R import com.pixelized.biblib.R
import com.pixelized.biblib.ui.composable.items.Image import com.pixelized.biblib.ui.composable.items.Image
import com.pixelized.biblib.ui.data.BookUio import com.pixelized.biblib.ui.data.BookUio
import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.ui.theme.Teal200 import com.pixelized.biblib.ui.theme.Teal200
import com.pixelized.biblib.ui.viewmodel.book.BooksViewModel
import com.pixelized.biblib.ui.viewmodel.book.IBooksViewModel
import com.pixelized.biblib.utils.BitmapCache import com.pixelized.biblib.utils.BitmapCache
import com.pixelized.biblib.utils.injection.Bob import com.pixelized.biblib.utils.injection.Bob
import com.pixelized.biblib.utils.mock.BookMock import com.pixelized.biblib.utils.mock.BookMock
@Composable
fun DetailPageComposable(
booksViewModel: IBooksViewModel = viewModel<BooksViewModel>(),
bookId: Int
) {
val book by booksViewModel.getBookDetail(bookId).observeAsState()
book?.let {
DetailPageComposable(book = it)
}
}
@Composable @Composable
fun DetailPageComposable(book: BookUio) { fun DetailPageComposable(book: BookUio) {
val typography = MaterialTheme.typography val typography = MaterialTheme.typography

View file

@ -1,6 +1,5 @@
package com.pixelized.biblib.ui.composable.pages package com.pixelized.biblib.ui.composable.pages
import android.util.Log
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
@ -18,7 +17,7 @@ import com.pixelized.biblib.ui.data.BookThumbnailUio
import com.pixelized.biblib.ui.theme.BibLibTheme import com.pixelized.biblib.ui.theme.BibLibTheme
import com.pixelized.biblib.ui.viewmodel.book.IBooksViewModel import com.pixelized.biblib.ui.viewmodel.book.IBooksViewModel
import com.pixelized.biblib.ui.viewmodel.navigation.INavigationViewModel import com.pixelized.biblib.ui.viewmodel.navigation.INavigationViewModel
import com.pixelized.biblib.ui.viewmodel.navigation.INavigationViewModel.Navigable.Page
@Preview @Preview
@Composable @Composable
@ -35,7 +34,8 @@ fun HomePageComposable(
navigationViewModel: INavigationViewModel, navigationViewModel: INavigationViewModel,
booksViewModel: IBooksViewModel booksViewModel: IBooksViewModel
) { ) {
val lazyBooks: LazyPagingItems<BookThumbnailUio> = booksViewModel.books.collectAsLazyPagingItems() val lazyBooks: LazyPagingItems<BookThumbnailUio> =
booksViewModel.books.collectAsLazyPagingItems()
LazyColumn( LazyColumn(
contentPadding = PaddingValues(16.dp), contentPadding = PaddingValues(16.dp),
@ -48,9 +48,7 @@ fun HomePageComposable(
.fillMaxWidth() .fillMaxWidth()
.wrapContentHeight(), .wrapContentHeight(),
) { item -> ) { item ->
// TODO: navigationViewModel.navigateTo(Page.Detail(item.id))
// val bookMock = BookMock().let { it.books[item.id] ?: it.book }
// navigation.navigateTo(INavigation.Page.Detail(bookMock))
} }
} }
} }

View file

@ -56,7 +56,7 @@ fun MainScreenComposable(
val page by navigationViewModel.page.observeAsState() val page by navigationViewModel.page.observeAsState()
LaunchedEffect(key1 = "MainScreen", block = { LaunchedEffect(key1 = "MainScreen", block = {
navigationViewModel.navigateTo(Page.HomePage) navigationViewModel.navigateTo(Page.HomePage, true)
}) })
Scaffold( Scaffold(
@ -76,10 +76,10 @@ fun MainScreenComposable(
enter = slideInHorizontally(initialOffsetX = { width -> width }), enter = slideInHorizontally(initialOffsetX = { width -> width }),
exit = slideOutHorizontally(targetOffsetX = { width -> width }), exit = slideOutHorizontally(targetOffsetX = { width -> width }),
) { ) {
// small trick to display the detail page during animation exit. // Small trick to display the detail page during animation exit.
var currentPage by remember { mutableStateOf<Page.Detail?>(null) } var currentPage by remember { mutableStateOf<Page.Detail?>(null) }
currentPage = page as? Page.Detail ?: currentPage currentPage = page as? Page.Detail ?: currentPage
currentPage?.let { DetailPageComposable(it.book) } currentPage?.let { DetailPageComposable(booksViewModel, it.bookId) }
} }
} }
} }

View file

@ -14,10 +14,12 @@ import com.pixelized.biblib.network.factory.BookFactory
import com.pixelized.biblib.repository.apiCache.IAPICacheRepository import com.pixelized.biblib.repository.apiCache.IAPICacheRepository
import com.pixelized.biblib.repository.book.IBookRepository import com.pixelized.biblib.repository.book.IBookRepository
import com.pixelized.biblib.ui.data.BookThumbnailUio import com.pixelized.biblib.ui.data.BookThumbnailUio
import com.pixelized.biblib.ui.data.BookUio
import com.pixelized.biblib.utils.injection.inject import com.pixelized.biblib.utils.injection.inject
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.*
class BooksViewModel : ViewModel(), IBooksViewModel { class BooksViewModel : ViewModel(), IBooksViewModel {
private val bookRepository: IBookRepository by inject() private val bookRepository: IBookRepository by inject()
@ -51,6 +53,17 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
} }
} }
override fun getBookDetail(id: Int): LiveData<BookUio> {
val data = MutableLiveData<BookUio>()
viewModelScope.launch(Dispatchers.IO) {
val factory = BookFactory()
val response = client.service.detail(id)
val book = factory.fromDetailResponseToBook(response)
data.postValue(book.toUio())
}
return data
}
private suspend fun loadNewBooks(): Boolean { private suspend fun loadNewBooks(): Boolean {
val cached = apiCache.new val cached = apiCache.new
val updated = client.service.new() val updated = client.service.new()
@ -79,4 +92,16 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
date = releaseDate.toString(), date = releaseDate.toString(),
series = series?.name, series = series?.name,
) )
private fun Book.toUio() = BookUio(
id = id,
title = title,
author = author.joinToString { it.name },
genre = genre?.joinToString { it.name } ?: "",
rating = rating?.toFloat() ?: 0.0f,
language = language?.code?.let { Locale(it).language } ?: "",
date = releaseDate.toString(),
series = series?.name,
description = synopsis ?: "",
)
} }

View file

@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.paging.PagingData import androidx.paging.PagingData
import com.pixelized.biblib.ui.data.BookThumbnailUio import com.pixelized.biblib.ui.data.BookThumbnailUio
import com.pixelized.biblib.ui.data.BookUio
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf
@ -14,6 +15,8 @@ interface IBooksViewModel {
fun updateBooks() fun updateBooks()
fun getBookDetail(id: Int): LiveData<BookUio>
sealed class State { sealed class State {
object Initial : State() object Initial : State()
object Loading : State() object Loading : State()
@ -28,5 +31,6 @@ interface IBooksViewModel {
get() = flowOf() get() = flowOf()
override fun updateBooks() = Unit override fun updateBooks() = Unit
override fun getBookDetail(id: Int) = MutableLiveData<BookUio>()
} }
} }

View file

@ -20,7 +20,7 @@ interface INavigationViewModel {
sealed class Page : Navigable() { sealed class Page : Navigable() {
object HomePage : Page() object HomePage : Page()
data class Detail(val book: BookUio) : Page() data class Detail(val bookId: Int) : Page()
} }
} }