From a822d7f008e0ed8f76a3f97560460098b380ebc6 Mon Sep 17 00:00:00 2001 From: Thomas Andres Gomez Date: Tue, 18 May 2021 14:00:30 +0200 Subject: [PATCH] Add new book management --- .../com/pixelized/biblib/BibLibApplication.kt | 1 + .../pixelized/biblib/database/dao/BookDao.kt | 4 + .../pixelized/biblib/database/data/BookDbo.kt | 3 + .../java/com/pixelized/biblib/model/Book.kt | 1 + .../biblib/network/factory/BookFactory.kt | 14 +- .../biblib/repository/book/BookRepository.kt | 5 +- .../biblib/repository/book/IBookRepository.kt | 2 + .../composable/screen/MainScreenComposable.kt | 2 +- .../biblib/ui/data/BookThumbnailUio.kt | 3 +- .../ui/viewmodel/book/BooksViewModel.kt | 22 +- .../ui/viewmodel/book/IBooksViewModel.kt | 5 + .../biblib/utils/mock/BookThumbnailMock.kt | 237 +----------------- 12 files changed, 63 insertions(+), 236 deletions(-) diff --git a/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt b/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt index de0e8c2..c02402f 100644 --- a/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt +++ b/app/src/main/java/com/pixelized/biblib/BibLibApplication.kt @@ -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. diff --git a/app/src/main/java/com/pixelized/biblib/database/dao/BookDao.kt b/app/src/main/java/com/pixelized/biblib/database/dao/BookDao.kt index f4040f1..70b9573 100644 --- a/app/src/main/java/com/pixelized/biblib/database/dao/BookDao.kt +++ b/app/src/main/java/com/pixelized/biblib/database/dao/BookDao.kt @@ -11,6 +11,10 @@ interface BookDao { @Query("SELECT * FROM ${BookDbo.TABLE}") fun getAll(): List + @Transaction + @Query("SELECT * FROM ${BookDbo.TABLE} WHERE ${BookDbo.IS_NEW} = 1 ORDER BY ${BookDbo.NEW_ORDER}") + fun getNews(): DataSource.Factory + @Transaction @Query("SELECT * FROM ${BookDbo.TABLE}") fun getBook(): DataSource.Factory diff --git a/app/src/main/java/com/pixelized/biblib/database/data/BookDbo.kt b/app/src/main/java/com/pixelized/biblib/database/data/BookDbo.kt index fbabe9c..4422037 100644 --- a/app/src/main/java/com/pixelized/biblib/database/data/BookDbo.kt +++ b/app/src/main/java/com/pixelized/biblib/database/data/BookDbo.kt @@ -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" } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/model/Book.kt b/app/src/main/java/com/pixelized/biblib/model/Book.kt index d2bd3bc..9495fe6 100644 --- a/app/src/main/java/com/pixelized/biblib/model/Book.kt +++ b/app/src/main/java/com/pixelized/biblib/model/Book.kt @@ -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 diff --git a/app/src/main/java/com/pixelized/biblib/network/factory/BookFactory.kt b/app/src/main/java/com/pixelized/biblib/network/factory/BookFactory.kt index 9942fab..89b363b 100644 --- a/app/src/main/java/com/pixelized/biblib/network/factory/BookFactory.kt +++ b/app/src/main/java/com/pixelized/biblib/network/factory/BookFactory.kt @@ -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, ) } diff --git a/app/src/main/java/com/pixelized/biblib/repository/book/BookRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/book/BookRepository.kt index a236ed2..a66f684 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/book/BookRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/book/BookRepository.kt @@ -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 = database.bookDao().getAll().map { it.toBook() } + override fun getNews(): DataSource.Factory = + database.bookDao().getNews().map { it.toBook() } + override fun getBook(): DataSource.Factory = 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( diff --git a/app/src/main/java/com/pixelized/biblib/repository/book/IBookRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/book/IBookRepository.kt index 8705890..88a32ca 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/book/IBookRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/book/IBookRepository.kt @@ -7,6 +7,8 @@ interface IBookRepository { fun getAll(): List + fun getNews(): DataSource.Factory + fun getBook(): DataSource.Factory suspend fun update(data: List) diff --git a/app/src/main/java/com/pixelized/biblib/ui/composable/screen/MainScreenComposable.kt b/app/src/main/java/com/pixelized/biblib/ui/composable/screen/MainScreenComposable.kt index f92891a..414cc85 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/composable/screen/MainScreenComposable.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/composable/screen/MainScreenComposable.kt @@ -74,7 +74,7 @@ fun MainScreenComposable( ) { Box { val lazyBooks: LazyPagingItems = - booksViewModel.books.collectAsLazyPagingItems() + booksViewModel.news.collectAsLazyPagingItems() val lazyListState = rememberLazyListState() val scrollableState = rememberScrollState() diff --git a/app/src/main/java/com/pixelized/biblib/ui/data/BookThumbnailUio.kt b/app/src/main/java/com/pixelized/biblib/ui/data/BookThumbnailUio.kt index 2ef6f82..3ada6f7 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/data/BookThumbnailUio.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/data/BookThumbnailUio.kt @@ -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") } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/BooksViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/BooksViewModel.kt index 93f5f7e..b470d9a 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/BooksViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/BooksViewModel.kt @@ -29,14 +29,24 @@ class BooksViewModel : ViewModel(), IBooksViewModel { private val _state = MutableLiveData(IBooksViewModel.State.Initial) override val state: LiveData get() = _state - private val source + private val bookSource get() = bookRepository.getBook() .map { it.toThumbnail() } .asPagingSourceFactory(Dispatchers.Default) override val books: Flow> = 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> = 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( diff --git a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/IBooksViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/IBooksViewModel.kt index 910ec3c..7fa5086 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/IBooksViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/viewmodel/book/IBooksViewModel.kt @@ -11,6 +11,8 @@ import kotlinx.coroutines.flow.flowOf interface IBooksViewModel { val state: LiveData + val news: Flow> + val books: Flow> fun updateBooks() @@ -27,6 +29,9 @@ interface IBooksViewModel { class Mock(initial: State = State.Initial) : IBooksViewModel { override val state: LiveData = MutableLiveData(initial) + override val news: Flow> + get() = flowOf() + override val books: Flow> get() = flowOf() diff --git a/app/src/main/java/com/pixelized/biblib/utils/mock/BookThumbnailMock.kt b/app/src/main/java/com/pixelized/biblib/utils/mock/BookThumbnailMock.kt index 8874794..10b60fd 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/mock/BookThumbnailMock.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/mock/BookThumbnailMock.kt @@ -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, ), ) }