diff --git a/app/schemas/com.pixelized.biblib.database.BibLibDatabase/1.json b/app/schemas/com.pixelized.biblib.database.BibLibDatabase/1.json index 11efb60..f115ed5 100644 --- a/app/schemas/com.pixelized.biblib.database.BibLibDatabase/1.json +++ b/app/schemas/com.pixelized.biblib.database.BibLibDatabase/1.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "3f612998c4903a247d1c955da20b272d", + "identityHash": "96272f43076988345569b6ad637a4e01", "entities": [ { "tableName": "AUTHOR", @@ -38,7 +38,7 @@ }, { "tableName": "BOOK", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`BOOK_ID` INTEGER NOT NULL, `BOOK_TITLE` TEXT NOT NULL, `BOOK_SORT` TEXT NOT NULL, `BOOK_HAVE_COVER` INTEGER NOT NULL, `BOOK_RELEASE_DATE` INTEGER NOT NULL, `BOOK_LANGUAGE_ID` INTEGER, `BOOK_RATING` INTEGER, `BOOK_SERIES_ID` INTEGER, `BOOK_SYNOPSIS` TEXT, `BOOK_ISNEW` INTEGER NOT NULL, `BOOK_NEW_ORDER` INTEGER, PRIMARY KEY(`BOOK_ID`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`BOOK_ID` INTEGER NOT NULL, `BOOK_TITLE` TEXT NOT NULL, `BOOK_SORT` TEXT NOT NULL, `BOOK_HAVE_COVER` INTEGER NOT NULL, `BOOK_RELEASE_DATE` INTEGER NOT NULL, `BOOK_LANGUAGE_ID` INTEGER, `BOOK_RATING` INTEGER, `BOOK_SERIES_ID` INTEGER, `BOOK_SERIES_INDEX` INTEGER, `BOOK_SYNOPSIS` TEXT, `BOOK_IS_NEW` INTEGER NOT NULL, `BOOK_NEW_ORDER` INTEGER, PRIMARY KEY(`BOOK_ID`))", "fields": [ { "fieldPath": "id", @@ -88,6 +88,12 @@ "affinity": "INTEGER", "notNull": false }, + { + "fieldPath": "seriesIndex", + "columnName": "BOOK_SERIES_INDEX", + "affinity": "INTEGER", + "notNull": false + }, { "fieldPath": "synopsis", "columnName": "BOOK_SYNOPSIS", @@ -96,7 +102,7 @@ }, { "fieldPath": "isNew", - "columnName": "BOOK_ISNEW", + "columnName": "BOOK_IS_NEW", "affinity": "INTEGER", "notNull": true }, @@ -170,7 +176,7 @@ }, { "tableName": "SERIES", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`SERIES_ID` INTEGER NOT NULL, `SERIES_NAME` TEXT NOT NULL, `SERIES_SORT` TEXT NOT NULL, `SERIES_INDEX` INTEGER, PRIMARY KEY(`SERIES_ID`))", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`SERIES_ID` INTEGER NOT NULL, `SERIES_NAME` TEXT NOT NULL, `SERIES_SORT` TEXT NOT NULL, PRIMARY KEY(`SERIES_ID`))", "fields": [ { "fieldPath": "id", @@ -189,12 +195,6 @@ "columnName": "SERIES_SORT", "affinity": "TEXT", "notNull": true - }, - { - "fieldPath": "index", - "columnName": "SERIES_INDEX", - "affinity": "INTEGER", - "notNull": false } ], "primaryKey": { @@ -284,7 +284,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '3f612998c4903a247d1c955da20b272d')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '96272f43076988345569b6ad637a4e01')" ] } } \ No newline at end of file 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 e8c3f6d..9c885f8 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 @@ -25,6 +25,8 @@ data class BookDbo( // details @ColumnInfo(name = SERIES_ID) val series: Int? = null, // one-to-many + @ColumnInfo(name = SERIES_INDEX) + val seriesIndex: Int? = null, @ColumnInfo(name = SYNOPSIS) val synopsis: String? = null, // source @@ -54,8 +56,9 @@ data class BookDbo( const val LANGUAGE_ID = "${TABLE}_LANGUAGE_ID" const val RATING = "${TABLE}_RATING" const val SERIES_ID = "${TABLE}_SERIES_ID" + const val SERIES_INDEX = "${TABLE}_SERIES_INDEX" const val SYNOPSIS = "${TABLE}_SYNOPSIS" - const val IS_NEW = "${TABLE}_ISNEW" + const val IS_NEW = "${TABLE}_IS_NEW" const val NEW_ORDER = "${TABLE}_NEW_ORDER" } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/database/data/SeriesDbo.kt b/app/src/main/java/com/pixelized/biblib/database/data/SeriesDbo.kt index 5a84ec8..78d5268 100644 --- a/app/src/main/java/com/pixelized/biblib/database/data/SeriesDbo.kt +++ b/app/src/main/java/com/pixelized/biblib/database/data/SeriesDbo.kt @@ -13,14 +13,11 @@ data class SeriesDbo( val name: String, @ColumnInfo(name = SORT) val sort: String, - @ColumnInfo(name = INDEX) - val index: Int?, ) { companion object { const val TABLE = "SERIES" const val ID = "${TABLE}_ID" const val NAME = "${TABLE}_NAME" const val SORT = "${TABLE}_SORT" - const val INDEX = "${TABLE}_INDEX" } } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/model/book/Book.kt b/app/src/main/java/com/pixelized/biblib/model/book/Book.kt index fbfe665..8f4a307 100644 --- a/app/src/main/java/com/pixelized/biblib/model/book/Book.kt +++ b/app/src/main/java/com/pixelized/biblib/model/book/Book.kt @@ -14,6 +14,7 @@ data class Book( val genre: List? = null, // details val series: Series? = null, + val seriesIndex: Int? = null, val synopsis: String? = null, // source val isNew: Boolean = false, diff --git a/app/src/main/java/com/pixelized/biblib/model/book/Series.kt b/app/src/main/java/com/pixelized/biblib/model/book/Series.kt index e807d40..e943dd7 100644 --- a/app/src/main/java/com/pixelized/biblib/model/book/Series.kt +++ b/app/src/main/java/com/pixelized/biblib/model/book/Series.kt @@ -4,5 +4,4 @@ data class Series( val id: Int, val name: String, val sort: String, - val index: Int?, ) \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt b/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt index 153fb90..3a389d1 100644 --- a/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt +++ b/app/src/main/java/com/pixelized/biblib/model/search/SortType.kt @@ -7,8 +7,5 @@ import androidx.compose.runtime.Stable @Immutable enum class SortType { Book, - Author, Series, - Genre, - Language; } \ No newline at end of file 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 6b02167..80856a5 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 @@ -13,7 +13,7 @@ class BookFactory { fun fromListResponseToBook( response: BookListResponse.Book, - seriesHash: Map, + seriesHash: SeriesHash, genreHash: Map>, isNew: Boolean = false, newOrder: Int? = null @@ -63,12 +63,6 @@ class BookFactory { } val rating = response.rating?.toIntOrNull() - val newOrder = if (isNew) { - newOrder - } else { - null - } - return Book( id = id ?: throw error("id"), title = title ?: throw error("title"), @@ -76,12 +70,13 @@ class BookFactory { author = author ?: throw error("author"), haveCover = cover ?: throw error("haveCover"), releaseDate = releaseDate ?: throw error("releaseDate"), - series = seriesHash[id], + series = seriesHash[id]?.second, + seriesIndex = seriesHash[id]?.first, language = language, rating = rating, genre = genreHash[id], isNew = isNew, - newOrder = newOrder, + newOrder = if (isNew) newOrder else null, ) } @@ -126,7 +121,7 @@ class BookFactory { val seriesSort = book.series_sort val seriesIndex: Int? = book.book_series_index?.toInt() val series: Series? = if (seriesId != null && seriesName != null && seriesSort != null) { - Series(id = seriesId, name = seriesName, sort = seriesSort, seriesIndex) + Series(id = seriesId, name = seriesName, sort = seriesSort) } else { null } @@ -151,6 +146,7 @@ class BookFactory { language = language ?: throw error("language"), rating = rating, series = series, + seriesIndex = seriesIndex, genre = tag, synopsis = synopsis, isNew = isNew diff --git a/app/src/main/java/com/pixelized/biblib/network/factory/SeriesFactory.kt b/app/src/main/java/com/pixelized/biblib/network/factory/SeriesFactory.kt index db9bf71..0316204 100644 --- a/app/src/main/java/com/pixelized/biblib/network/factory/SeriesFactory.kt +++ b/app/src/main/java/com/pixelized/biblib/network/factory/SeriesFactory.kt @@ -4,26 +4,28 @@ import com.pixelized.biblib.model.book.Series import com.pixelized.biblib.network.data.response.SeriesListResponse import com.pixelized.biblib.utils.exception.missingField +typealias SeriesHash = Map> + class SeriesFactory { fun fromListResponseToSeriesHash( response: SeriesListResponse, - ): Map { + ): SeriesHash { fun error(name: String) = missingField("#fromListResponseToSeriesHash()", name, response) - val hash = mutableMapOf() + // BOOK_ID, BOOK_SERIES_INDEX, SERIES + val hash = mutableMapOf>() - response.series?.forEachIndexed { index, data -> + response.series?.forEach { data -> // build the Series items val series = Series( id = data.series_id ?: throw error("id"), name = data.series_name ?: throw error("name"), sort = data.series_sort ?: throw error("sort"), - index = index, ) // link that item to the book id. - data.books?.forEach { book -> - book.book_id?.let { id -> hash[id] = series } + data.books?.forEachIndexed { index, book -> + book.book_id?.let { id -> hash[id] = (index + 1) to series } } } 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 d8a9e24..55143d2 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 @@ -61,9 +61,7 @@ class BookRepository @Inject constructor( languages.add(it.toDbo()) } book.series?.let { - if (it.id != null) { - series.add(it.toDbo(it.id)) - } + series.add(it.toDbo(it.id)) } books.add(book.toDbo()) } @@ -93,7 +91,6 @@ class BookRepository @Inject constructor( id = id, name = name, sort = sort, - index = index, ) private fun Language.toDbo() = LanguageDbo( @@ -110,6 +107,7 @@ class BookRepository @Inject constructor( language = language?.id, rating = rating, series = series?.id, + seriesIndex = seriesIndex, synopsis = synopsis, isNew = isNew, newOrder = newOrder, @@ -126,6 +124,7 @@ class BookRepository @Inject constructor( rating = book.rating, genre = genres?.map { it.toGenre() }, series = series?.toSeries(), + seriesIndex = book.seriesIndex, synopsis = book.synopsis, isNew = book.isNew, ) @@ -150,6 +149,5 @@ class BookRepository @Inject constructor( id = id, name = name, sort = sort, - index = index, ) } \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt index d044638..65e728d 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/search/ISearchRepository.kt @@ -11,6 +11,7 @@ interface ISearchRepository { seriesId: Int?, genreId: Int?, languageId: Int?, + sortBy : SortType, limit: Int, offset: Int, ): List diff --git a/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt b/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt index 8be1c55..939ef06 100644 --- a/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt +++ b/app/src/main/java/com/pixelized/biblib/repository/search/SearchRepository.kt @@ -20,6 +20,7 @@ class SearchRepository @Inject constructor( seriesId: Int?, genreId: Int?, languageId: Int?, + sortBy : SortType, limit: Int, offset: Int ): List { @@ -43,7 +44,10 @@ class SearchRepository @Inject constructor( query += args.where(argument = languageId) { BookDbo.run { "$TABLE.$LANGUAGE_ID LIKE ?" } } - query += BookDbo.run { " ORDER BY $TABLE.$SORT" } + query += when (sortBy) { + SortType.Book -> BookDbo.run { " ORDER BY $TABLE.$SORT" } + SortType.Series -> BookDbo.run { " ORDER BY $TABLE.$SERIES_INDEX" } + } // Limit and Offset the query. query += " LIMIT $limit OFFSET $offset;" // compute the query @@ -143,6 +147,7 @@ private fun BookRelation.toBook(): Book = Book( rating = book.rating, genre = genres?.map { it.toGenre() }, series = series?.toSeries(), + seriesIndex = book.seriesIndex, synopsis = book.synopsis, isNew = book.isNew, ) @@ -167,5 +172,4 @@ private fun SeriesDbo.toSeries() = Series( id = id, name = name, sort = sort, - index = index, ) \ No newline at end of file diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt index fcdda2b..c1fed3e 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/common/item/MicroBookThumbnail.kt @@ -29,10 +29,11 @@ import com.skydoves.landscapist.glide.GlideImage @Stable data class MicroBookThumbnailUio( val id: Int, + val cover: String, val title: String, val author: String, + val series: String, val isNew: Boolean, - val cover: String, ) @Composable @@ -71,7 +72,7 @@ private fun MicroBookThumbnailContent( ConstraintLayout( modifier = Modifier.fillMaxWidth(), ) { - val (cover, title, author) = createRefs() + val (cover, title, author, series) = createRefs() GlideImage( modifier = Modifier @@ -95,25 +96,37 @@ private fun MicroBookThumbnailContent( }, style = MaterialTheme.typography.body1, color = MaterialTheme.bibLib.colors.typography.medium, - text = thumbnail.title, - maxLines = 1, overflow = TextOverflow.Ellipsis, + maxLines = 1, + text = thumbnail.title, ) Text( modifier = Modifier.constrainAs(author) { top.linkTo(title.bottom, margin = dimen.dp4) - bottom.linkTo(parent.bottom, 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.caption, color = MaterialTheme.bibLib.colors.typography.easy, - maxLines = 1, overflow = TextOverflow.Ellipsis, - text = thumbnail.author + maxLines = 1, + text = thumbnail.author, + ) + + Text( + modifier = Modifier.constrainAs(series) { + top.linkTo(author.bottom, margin = dimen.dp4) + start.linkTo(cover.end, margin = dimen.dp8) + end.linkTo(parent.end, margin = dimen.dp8) + width = Dimension.fillToConstraints + }, + style = MaterialTheme.typography.caption, + color = MaterialTheme.bibLib.colors.typography.easy, + overflow = TextOverflow.Ellipsis, + maxLines = 1, + text = thumbnail.series, ) } } @@ -186,10 +199,11 @@ private fun MicroBookThumbnailPreview() { MicroBookThumbnail( thumbnail = MicroBookThumbnailUio( id = 0, + cover = "", title = "Foundation", author = "Asimov", + series = "Foundation - 1", isNew = false, - cover = "", ) ) } diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/source/BookSearchSource.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/source/BookSearchSource.kt index 50a08ad..9395fc5 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/source/BookSearchSource.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/source/BookSearchSource.kt @@ -4,6 +4,7 @@ import android.util.Log import androidx.paging.PagingSource import androidx.paging.PagingState import com.pixelized.biblib.model.book.Book +import com.pixelized.biblib.model.search.SortType import com.pixelized.biblib.repository.search.ISearchRepository import com.pixelized.biblib.utils.extention.page @@ -13,6 +14,7 @@ class BookSearchSource( private val authorId: Int?, private val seriesId: Int?, private val genreId: Int?, + private val sortBy: SortType, private val languageId: Int?, private val limit: Int, ) : PagingSource() { @@ -30,6 +32,7 @@ class BookSearchSource( seriesId = seriesId, genreId = genreId, languageId = languageId, + sortBy = sortBy, limit = limit, offset = index * limit ) diff --git a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt index 2030bfb..5c28c54 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/screen/home/page/search/viewModel/BookSearchViewModel.kt @@ -7,6 +7,7 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import androidx.paging.* import com.pixelized.biblib.model.book.Book +import com.pixelized.biblib.model.search.SortType import com.pixelized.biblib.repository.search.ISearchRepository import com.pixelized.biblib.ui.screen.home.common.item.MicroBookThumbnailUio import com.pixelized.biblib.ui.screen.home.page.search.bottom.FilterUio @@ -83,6 +84,7 @@ class BookSearchViewModel @Inject constructor( authorId = author?.id, seriesId = series?.id, genreId = genre?.id, + sortBy = if (series != null) SortType.Series else SortType.Book, languageId = language?.id, limit = SEARCH_PAGE_SIZE, ).also { diff --git a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt index 606b614..1c6a989 100644 --- a/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt +++ b/app/src/main/java/com/pixelized/biblib/ui/theme/dimen/BibLibDimen.kt @@ -38,7 +38,7 @@ data class BibLibDimen( val padding: Dp = 16.dp, val arrangement: Dp = 16.dp, val cover: DpSize = 72.dp.let { DpSize(width = it, height = it * ratio) }, - val micro: DpSize = 48.dp.let { DpSize(width = it, height = it * ratio) }, + val micro: DpSize = 50.dp.let { DpSize(width = it, height = it * ratio) }, ) @Stable diff --git a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt index 1cb3ef1..847e6eb 100644 --- a/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt +++ b/app/src/main/java/com/pixelized/biblib/utils/extention/BookEx.kt @@ -24,6 +24,7 @@ fun Book.toMicroThumbnailUio( cover = "${coverBaseUrl}/$id.jpg", title = title, author = author.joinToString { it.name }, + series = toLabel(series) ?: "", isNew = isNew, ) @@ -59,15 +60,15 @@ fun Book.toDetailUio( rating = rating?.toFloat() ?: 0.0f, language = language?.displayLanguage?.capitalize() ?: "", date = releaseDate.shortDate(), - series = series.toLabel(), + series = toLabel(series), description = synopsis ?: "", cover = "${coverBaseUrl}/$id.jpg", ) -fun Series?.toLabel(): String? { +fun Book.toLabel(series: Series?): String? { return when { - this != null && index != null -> "$name - $index" - this != null -> name + series?.name != null && seriesIndex != null -> "${series.name} - $seriesIndex" + series?.name != null -> series.name else -> null } } \ No newline at end of file