diff --git a/app/src/main/java/io/legado/app/data/dao/BookDao.kt b/app/src/main/java/io/legado/app/data/dao/BookDao.kt index 561b9a2c4..00cff7098 100644 --- a/app/src/main/java/io/legado/app/data/dao/BookDao.kt +++ b/app/src/main/java/io/legado/app/data/dao/BookDao.kt @@ -13,7 +13,6 @@ import io.legado.app.data.entities.BookGroup import io.legado.app.data.entities.BookSource import io.legado.app.help.book.isNotShelf import io.legado.app.ui.main.bookshelf.BookShelfItem -import io.legado.app.ui.main.bookshelf.toBookShelfItem import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.map @@ -41,8 +40,22 @@ interface BookDao { } fun flowBookShelfByGroup(groupId: Long): Flow> { - return flowByGroup(groupId).map { list -> - list.map { it.toBookShelfItem() } + return when (groupId) { + BookGroup.IdRoot -> flowBookShelfRoot() + BookGroup.IdAll -> flowBookShelf() + BookGroup.IdLocal -> flowBookShelfLocal() + BookGroup.IdAudio -> flowBookShelfAudio() + BookGroup.IdNetNone -> flowBookShelfNetNoGroup() + BookGroup.IdLocalNone -> flowBookShelfLocalNoGroup() + BookGroup.IdManga -> flowBookShelfManga() + BookGroup.IdText -> flowBookShelfText() + BookGroup.IdError -> flowBookShelfUpdateError() + BookGroup.IdUnread -> flowBookShelfUnread() + BookGroup.IdReading -> flowBookShelfReading() + BookGroup.IdReadFinished -> flowBookShelfReadFinished() + else -> flowBookShelfByUserGroup(groupId) + }.map { list -> + list.filterNot { it.isNotShelf } } } @@ -56,6 +69,34 @@ interface BookDao { ) fun flowRoot(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + where type & ${BookType.text} > 0 + and type & ${BookType.local} = 0 + and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0 + and (select show from book_groups where groupId = ${BookGroup.IdNetNone}) != 1 + """ + ) + fun flowBookShelfRoot(): Flow> + @Query("SELECT * FROM books order by durChapterTime desc") fun flowAll(): Flow> @@ -87,9 +128,59 @@ interface BookDao { @Query("SELECT * FROM books WHERE type & ${BookType.audio} > 0") fun flowAudio(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE type & ${BookType.audio} > 0 + """ + ) + fun flowBookShelfAudio(): Flow> + @Query("SELECT * FROM books WHERE type & ${BookType.local} > 0") fun flowLocal(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE type & ${BookType.local} > 0 + """ + ) + fun flowBookShelfLocal(): Flow> + @Query( """ select * from books where type & ${BookType.audio} = 0 and type & ${BookType.local} = 0 @@ -98,6 +189,32 @@ interface BookDao { ) fun flowNetNoGroup(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + where type & ${BookType.audio} = 0 and type & ${BookType.local} = 0 + and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0 + """ + ) + fun flowBookShelfNetNoGroup(): Flow> + @Query( """ select * from books where type & ${BookType.local} > 0 @@ -106,30 +223,257 @@ interface BookDao { ) fun flowLocalNoGroup(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + where type & ${BookType.local} > 0 + and ((SELECT sum(groupId) FROM book_groups where groupId > 0) & `group`) = 0 + """ + ) + fun flowBookShelfLocalNoGroup(): Flow> + @Query("SELECT * FROM books WHERE (`group` & :group) > 0") fun flowByUserGroup(group: Long): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE (`group` & :group) > 0 + """ + ) + fun flowBookShelfByUserGroup(group: Long): Flow> + @Query("SELECT * FROM books WHERE name like '%'||:key||'%' or author like '%'||:key||'%'") fun flowSearch(key: String): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE name like '%'||:key||'%' or author like '%'||:key||'%' + """ + ) + fun flowBookShelfSearch(key: String): Flow> + @Query("SELECT * FROM books where type & ${BookType.updateError} > 0 order by durChapterTime desc") fun flowUpdateError(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + where type & ${BookType.updateError} > 0 + order by durChapterTime desc + """ + ) + fun flowBookShelfUpdateError(): Flow> + @Query("""SELECT * FROM books WHERE durChapterIndex = 0 AND durChapterPos = 0""") fun flowUnread(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE durChapterIndex = 0 AND durChapterPos = 0 + """ + ) + fun flowBookShelfUnread(): Flow> + @Query("""SELECT * FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1""") fun flowReadFinished(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 + """ + ) + fun flowBookShelfReadFinished(): Flow> + @Query("""SELECT * FROM books WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1""") fun flowReading(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1 + """ + ) + fun flowBookShelfReading(): Flow> + @Query("SELECT * FROM books WHERE type & ${BookType.image} > 0") fun flowManga(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE type & ${BookType.image} > 0 + """ + ) + fun flowBookShelfManga(): Flow> + @Query("SELECT * FROM books WHERE type & ${BookType.text} > 0") fun flowText(): Flow> + @Query( + """ + SELECT + bookUrl, + name, + author, + coverUrl, + customCoverUrl, + durChapterTitle, + durChapterTime, + durChapterPos, + latestChapterTitle, + latestChapterTime, + totalChapterNum, + durChapterIndex, + type, + `group`, + `order`, + canUpdate + FROM books + WHERE type & ${BookType.text} > 0 + """ + ) + fun flowBookShelfText(): Flow> + @Query("SELECT * FROM books WHERE (`group` & :group) > 0") fun getBooksByGroup(group: Long): List diff --git a/app/src/main/java/io/legado/app/model/BookCover.kt b/app/src/main/java/io/legado/app/model/BookCover.kt index 26c951846..73bcc862c 100644 --- a/app/src/main/java/io/legado/app/model/BookCover.kt +++ b/app/src/main/java/io/legado/app/model/BookCover.kt @@ -77,15 +77,25 @@ object BookCover { return paths[random.nextInt(paths.size)] } + // 缓存随机封面 Drawable,避免重复解码 + private val randomDrawableCache = mutableMapOf() + fun getRandomDefaultDrawable( seed: Any? = null, isNight: Boolean = AppConfig.isNightTheme ): Drawable { val randomPath = getRandomDefaultPath(seed, isNight) ?: return appCtx.resources.getDrawable(R.drawable.image_cover_default, null) - return kotlin.runCatching { - BitmapUtils.decodeBitmap(randomPath, 600, 900)!!.toDrawable(appCtx.resources) - }.getOrDefault(appCtx.resources.getDrawable(R.drawable.image_cover_default, null)) + + // 生成缓存键 + val cacheKey = "$randomPath-${isNight}" + + // 从缓存中获取,如果没有则解码并缓存 + return randomDrawableCache.getOrPut(cacheKey) { + kotlin.runCatching { + BitmapUtils.decodeBitmap(randomPath, 600, 900)!!.toDrawable(appCtx.resources) + }.getOrDefault(appCtx.resources.getDrawable(R.drawable.image_cover_default, null)) + } } /** diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt index 2d287df19..4d9a3054e 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookShelfItem.kt @@ -32,6 +32,8 @@ data class BookShelfItem( val isImage: Boolean get() = (type and BookType.image) > 0 + val isNotShelf: Boolean get() = (type and BookType.notShelf) > 0 + fun getUnreadChapterNum() = max(totalChapterNum - durChapterIndex - 1, 0) }