From b79f749e7a2c990d9ba756c6c9cccbe1a7124f41 Mon Sep 17 00:00:00 2001 From: HapeLee <1321903405@qq.com> Date: Tue, 24 Mar 2026 01:15:45 +0800 Subject: [PATCH] =?UTF-8?q?[=E4=BF=AE=E5=A4=8D]=20=E4=BE=9D=E6=97=A7?= =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=B0=81=E9=9D=A2=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/model/BookCover.kt | 7 +++- .../ui/main/bookshelf/BookshelfViewModel.kt | 41 +++++++++++++++++-- .../ui/widget/components/cover/BookCover.kt | 28 ++++++++++--- 3 files changed, 65 insertions(+), 11 deletions(-) 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 4a6a980a9..26c951846 100644 --- a/app/src/main/java/io/legado/app/model/BookCover.kt +++ b/app/src/main/java/io/legado/app/model/BookCover.kt @@ -77,8 +77,11 @@ object BookCover { return paths[random.nextInt(paths.size)] } - fun getRandomDefaultDrawable(seed: Any? = null): Drawable { - val randomPath = getRandomDefaultPath(seed) + 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) diff --git a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt index c1c27a9c0..fe70a57f3 100644 --- a/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt @@ -137,10 +137,43 @@ class BookshelfViewModel( combine(groupsFlow, allBooksFlow, refreshTrigger) { groups, allBooks, _ -> if (BookshelfConfig.bookGroupStyle in 2..3) { groups.associate { group -> - val groupBooks = if (group.groupId == BookGroup.IdAll) { - allBooks - } else { - allBooks.filter { (it.group and group.groupId) != 0L } + val groupBooks = when (group.groupId) { + BookGroup.IdRoot -> { + val sumUserGroupIds = groups.filter { it.groupId > 0 }.sumOf { it.groupId } + allBooks.filter { book -> + (book.type and BookType.text) > 0 && + (book.type and BookType.local) == 0 && + (sumUserGroupIds and book.group) == 0L + } + } + + BookGroup.IdAll -> allBooks + BookGroup.IdLocal -> allBooks.filter { (it.type and BookType.local) > 0 } + BookGroup.IdAudio -> allBooks.filter { (it.type and BookType.audio) > 0 } + BookGroup.IdNetNone -> { + val sumUserGroupIds = groups.filter { it.groupId > 0 }.sumOf { it.groupId } + allBooks.filter { book -> + (book.type and BookType.audio) == 0 && + (book.type and BookType.local) == 0 && + (sumUserGroupIds and book.group) == 0L + } + } + + BookGroup.IdLocalNone -> { + val sumUserGroupIds = groups.filter { it.groupId > 0 }.sumOf { it.groupId } + allBooks.filter { book -> + (book.type and BookType.local) > 0 && + (sumUserGroupIds and book.group) == 0L + } + } + + BookGroup.IdManga -> allBooks.filter { (it.type and BookType.image) > 0 } + BookGroup.IdText -> allBooks.filter { (it.type and BookType.text) > 0 } + BookGroup.IdError -> allBooks.filter { (it.type and BookType.updateError) > 0 } + BookGroup.IdUnread -> allBooks.filter { it.durChapterIndex == 0 && it.durChapterPos == 0 } + BookGroup.IdReading -> allBooks.filter { it.totalChapterNum > 0 && it.durChapterIndex > 0 && it.durChapterIndex < it.totalChapterNum - 1 } + BookGroup.IdReadFinished -> allBooks.filter { it.totalChapterNum > 0 && it.durChapterIndex >= it.totalChapterNum - 1 } + else -> allBooks.filter { (it.group and group.groupId) != 0L } } val sortedBooks = sortBooks(groupBooks, group) val booksWithCover = sortedBooks.filter { it.getDisplayCover() != null } diff --git a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookCover.kt b/app/src/main/java/io/legado/app/ui/widget/components/cover/BookCover.kt index fd0772934..ead7413f1 100644 --- a/app/src/main/java/io/legado/app/ui/widget/components/cover/BookCover.kt +++ b/app/src/main/java/io/legado/app/ui/widget/components/cover/BookCover.kt @@ -13,13 +13,10 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Book import androidx.compose.material.icons.filled.Update -import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -75,6 +72,18 @@ fun BookCover( ) } + // 获取随机封面 Drawable,用于占位图 + val randomDrawable = remember( + name, author, path, isNight, + CoverConfig.defaultCover, + CoverConfig.defaultCoverDark + ) { + BookCover.getRandomDefaultDrawable( + seed = name ?: author ?: path ?: "", + isNight = isNight + ) + } + // 检查是否有自定义随机封面设置 val hasCustomDefault = !randomPath.isNullOrBlank() @@ -89,9 +98,15 @@ fun BookCover( } else Modifier ) .clip(RoundedCornerShape(4.dp)) - .background(MaterialTheme.colorScheme.surfaceContainer) + .then( + if (!hasCustomDefault) { + Modifier.background(MaterialTheme.colorScheme.surfaceContainer) + } else Modifier + ) ) { // 如果没有自定义随机封面,显示书本图标作为底图 + // TODO:暂时先用猫猫头 + /* if (!hasCustomDefault) { Icon( Icons.Default.Book, @@ -102,12 +117,15 @@ fun BookCover( .align(Alignment.Center) ) } + */ + // 1. 封面图层 AsyncImage( model = ImageRequest.Builder(context) .data(finalPath ?: randomPath) - // 限制解码分辨率 + .placeholder(randomDrawable) + .error(randomDrawable) .size(400, 560) .crossfade(true) .setParameter("sourceOrigin", sourceOrigin)