Add new book management
This commit is contained in:
parent
bb9e1b36f7
commit
a822d7f008
12 changed files with 63 additions and 236 deletions
|
|
@ -28,6 +28,7 @@ class BibLibApplication : Application() {
|
|||
// Android.
|
||||
Bob[BibLibDatabase::class] =
|
||||
Room.databaseBuilder(this, BibLibDatabase::class.java, BibLibDatabase.DATABASE_NAME)
|
||||
.fallbackToDestructiveMigration()
|
||||
.build()
|
||||
Bob[SharedPreferences::class] = getSharedPreferences(SHARED_PREF, Context.MODE_PRIVATE)
|
||||
// Web service.
|
||||
|
|
|
|||
|
|
@ -11,6 +11,10 @@ interface BookDao {
|
|||
@Query("SELECT * FROM ${BookDbo.TABLE}")
|
||||
fun getAll(): List<BookRelation>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM ${BookDbo.TABLE} WHERE ${BookDbo.IS_NEW} = 1 ORDER BY ${BookDbo.NEW_ORDER}")
|
||||
fun getNews(): DataSource.Factory<Int, BookRelation>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM ${BookDbo.TABLE}")
|
||||
fun getBook(): DataSource.Factory<Int, BookRelation>
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ data class BookDbo(
|
|||
// source
|
||||
@ColumnInfo(name = IS_NEW)
|
||||
val isNew: Boolean = false,
|
||||
@ColumnInfo(name = NEW_ORDER)
|
||||
val newOrder: Int? = null,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
|
@ -54,5 +56,6 @@ data class BookDbo(
|
|||
const val SERIES_ID = "${TABLE}_SERIES_ID"
|
||||
const val SYNOPSIS = "${TABLE}_SYNOPSIS"
|
||||
const val IS_NEW = "${TABLE}_ISNEW"
|
||||
const val NEW_ORDER = "${TABLE}_NEW_ORDER"
|
||||
}
|
||||
}
|
||||
|
|
@ -17,6 +17,7 @@ data class Book(
|
|||
val synopsis: String? = null,
|
||||
// source
|
||||
val isNew: Boolean = false,
|
||||
val newOrder: Int? = null,
|
||||
) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
|
|
|
|||
|
|
@ -11,7 +11,11 @@ import java.util.*
|
|||
class BookFactory {
|
||||
private val parser get() = SimpleDateFormat(FORMAT, Locale.getDefault())
|
||||
|
||||
fun fromListResponseToBook(response: BookListResponse.Book, isNew: Boolean = false): Book {
|
||||
fun fromListResponseToBook(
|
||||
response: BookListResponse.Book,
|
||||
isNew: Boolean = false,
|
||||
newOrder: Int? = null
|
||||
): Book {
|
||||
fun error(name: String) =
|
||||
MandatoryFieldMissingException("#fromListResponseToBook()", name, response)
|
||||
|
||||
|
|
@ -65,6 +69,11 @@ class BookFactory {
|
|||
} else {
|
||||
null
|
||||
}
|
||||
val newOrder = if (isNew) {
|
||||
newOrder
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
return Book(
|
||||
id = id ?: throw error("id"),
|
||||
|
|
@ -76,7 +85,8 @@ class BookFactory {
|
|||
series = series,
|
||||
language = language,
|
||||
rating = rating,
|
||||
isNew = isNew
|
||||
isNew = isNew,
|
||||
newOrder = newOrder,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package com.pixelized.biblib.repository.book
|
||||
|
||||
|
||||
import android.util.Log
|
||||
import androidx.paging.DataSource
|
||||
import com.pixelized.biblib.database.BibLibDatabase
|
||||
import com.pixelized.biblib.database.crossref.BookAuthorCrossRef
|
||||
|
|
@ -17,6 +16,9 @@ class BookRepository : IBookRepository {
|
|||
override fun getAll(): List<Book> =
|
||||
database.bookDao().getAll().map { it.toBook() }
|
||||
|
||||
override fun getNews(): DataSource.Factory<Int, Book> =
|
||||
database.bookDao().getNews().map { it.toBook() }
|
||||
|
||||
override fun getBook(): DataSource.Factory<Int, Book> =
|
||||
database.bookDao().getBook().map { it.toBook() }
|
||||
|
||||
|
|
@ -92,6 +94,7 @@ class BookRepository : IBookRepository {
|
|||
series = series?.id,
|
||||
synopsis = synopsis,
|
||||
isNew = isNew,
|
||||
newOrder = newOrder,
|
||||
)
|
||||
|
||||
private fun BookRelation.toBook(): Book = Book(
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ interface IBookRepository {
|
|||
|
||||
fun getAll(): List<Book>
|
||||
|
||||
fun getNews(): DataSource.Factory<Int, Book>
|
||||
|
||||
fun getBook(): DataSource.Factory<Int, Book>
|
||||
|
||||
suspend fun update(data: List<Book>)
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ fun MainScreenComposable(
|
|||
) {
|
||||
Box {
|
||||
val lazyBooks: LazyPagingItems<BookThumbnailUio> =
|
||||
booksViewModel.books.collectAsLazyPagingItems()
|
||||
booksViewModel.news.collectAsLazyPagingItems()
|
||||
val lazyListState = rememberLazyListState()
|
||||
val scrollableState = rememberScrollState()
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ data class BookThumbnailUio(
|
|||
val title: String,
|
||||
val author: String,
|
||||
val date: String,
|
||||
val series: String?
|
||||
val series: String?,
|
||||
val isNew: Boolean,
|
||||
) {
|
||||
val cover: URL = URL("${THUMBNAIL_URL}/$id.jpg")
|
||||
}
|
||||
|
|
@ -29,14 +29,24 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
private val _state = MutableLiveData<IBooksViewModel.State>(IBooksViewModel.State.Initial)
|
||||
override val state: LiveData<IBooksViewModel.State> get() = _state
|
||||
|
||||
private val source
|
||||
private val bookSource
|
||||
get() = bookRepository.getBook()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.Default)
|
||||
|
||||
override val books: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = source
|
||||
pagingSourceFactory = bookSource
|
||||
).flow
|
||||
|
||||
private val newsSource
|
||||
get() = bookRepository.getNews()
|
||||
.map { it.toThumbnail() }
|
||||
.asPagingSourceFactory(Dispatchers.Default)
|
||||
|
||||
override val news: Flow<PagingData<BookThumbnailUio>> = Pager(
|
||||
config = PagingConfig(pageSize = PAGING_SIZE),
|
||||
pagingSourceFactory = newsSource
|
||||
).flow
|
||||
|
||||
override fun updateBooks() {
|
||||
|
|
@ -77,8 +87,13 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
|
||||
private suspend fun loadAllBooks(): Boolean {
|
||||
client.service.list().let { response ->
|
||||
val newIds = apiCache.new?.data?.map { it.book_id } ?: listOf()
|
||||
val factory = BookFactory()
|
||||
val books = response.data?.map { dto -> factory.fromListResponseToBook(dto, false) }
|
||||
val books = response.data?.map { dto ->
|
||||
val isNew = newIds.contains(dto.book_id)
|
||||
val index = newIds.indexOf(dto.book_id)
|
||||
factory.fromListResponseToBook(dto, isNew, index)
|
||||
}
|
||||
books?.let { data -> bookRepository.update(data) }
|
||||
}
|
||||
return true
|
||||
|
|
@ -91,6 +106,7 @@ class BooksViewModel : ViewModel(), IBooksViewModel {
|
|||
author = author.joinToString { it.name },
|
||||
date = releaseDate.toString(),
|
||||
series = series?.name,
|
||||
isNew = isNew,
|
||||
)
|
||||
|
||||
private fun Book.toUio() = BookUio(
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import kotlinx.coroutines.flow.flowOf
|
|||
interface IBooksViewModel {
|
||||
val state: LiveData<State>
|
||||
|
||||
val news: Flow<PagingData<BookThumbnailUio>>
|
||||
|
||||
val books: Flow<PagingData<BookThumbnailUio>>
|
||||
|
||||
fun updateBooks()
|
||||
|
|
@ -27,6 +29,9 @@ interface IBooksViewModel {
|
|||
class Mock(initial: State = State.Initial) : IBooksViewModel {
|
||||
override val state: LiveData<State> = MutableLiveData(initial)
|
||||
|
||||
override val news: Flow<PagingData<BookThumbnailUio>>
|
||||
get() = flowOf()
|
||||
|
||||
override val books: Flow<PagingData<BookThumbnailUio>>
|
||||
get() = flowOf()
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,8 @@ class BookThumbnailMock {
|
|||
title = "Foundation",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 1"
|
||||
series = "Foundation - 1",
|
||||
isNew = false,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -25,6 +26,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 78,
|
||||
|
|
@ -33,6 +35,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 90,
|
||||
|
|
@ -41,6 +44,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 184,
|
||||
|
|
@ -49,6 +53,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 185,
|
||||
|
|
@ -57,6 +62,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 119,
|
||||
|
|
@ -65,6 +71,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
isNew = false,
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 163,
|
||||
|
|
@ -73,233 +80,7 @@ class BookThumbnailMock {
|
|||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
),
|
||||
|
||||
|
||||
|
||||
BookThumbnailUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 112,
|
||||
title = "Prélude à Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1988",
|
||||
series = "Foundation - 1",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 78,
|
||||
title = "L'Aube de Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1993",
|
||||
series = "Foundation - 2",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 90,
|
||||
title = "Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1951",
|
||||
series = "Foundation - 3",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 184,
|
||||
title = "Fondation et Empire",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1952",
|
||||
series = "Foundation - 4",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 185,
|
||||
title = "Seconde Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1953",
|
||||
series = "Foundation - 5",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 119,
|
||||
title = "Fondation foudroyée",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1982",
|
||||
series = "Foundation - 6",
|
||||
),
|
||||
BookThumbnailUio(
|
||||
id = 163,
|
||||
title = "Terre et Fondation",
|
||||
genre = "Sci-Fi",
|
||||
author = "Asimov",
|
||||
date = "1986",
|
||||
series = "Foundation - 7",
|
||||
isNew = false,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue