Просмотр исходного кода

feat: 添加连载已读/完本已读分组,基于canUpdate字段自动分类

HapeLee 4 месяцев назад
Родитель
Сommit
4b65d6fc71

+ 24 - 3
app/src/main/java/io/legado/app/data/AppDatabase.kt

@@ -16,6 +16,8 @@ import io.legado.app.data.dao.CacheDao
 import io.legado.app.data.dao.CookieDao
 import io.legado.app.data.dao.DictRuleDao
 import io.legado.app.data.dao.HighlightRuleDao
+import io.legado.app.data.dao.HighlightTagRuleDao
+import io.legado.app.data.dao.TagGroupRuleDao
 import io.legado.app.data.dao.HomepageCustomSetDao
 import io.legado.app.data.dao.HomepageModuleDao
 import io.legado.app.data.dao.HttpTTSDao
@@ -42,6 +44,8 @@ import io.legado.app.data.entities.Cache
 import io.legado.app.data.entities.Cookie
 import io.legado.app.data.entities.DictRule
 import io.legado.app.data.entities.HighlightRule
+import io.legado.app.data.entities.HighlightTagRule
+import io.legado.app.data.entities.TagGroupRule
 import io.legado.app.data.entities.HomepageCustomSet
 import io.legado.app.data.entities.HomepageModule
 import io.legado.app.data.entities.HttpTTS
@@ -75,7 +79,7 @@ val appDb by lazy {
 }
 
 @Database(
-    version = 91,
+    version = 92,
     exportSchema = true,
     entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
         ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
@@ -84,7 +88,7 @@ val appDb by lazy {
         RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class, Cache::class,
         RuleSub::class, DictRule::class, KeyboardAssist::class, Server::class,
         SearchContentHistory::class, HomepageModule::class, HomepageCustomSet::class,
-        HighlightRule::class],
+        HighlightRule::class, HighlightTagRule::class, TagGroupRule::class],
     views = [BookSourcePart::class],
     autoMigrations = [
         AutoMigration(from = 43, to = 44),
@@ -134,7 +138,8 @@ val appDb by lazy {
         AutoMigration(from = 87, to = 88),
         AutoMigration(from = 88, to = 89),
         AutoMigration(from = 89, to = 90),
-        AutoMigration(from = 90, to = 91)
+        AutoMigration(from = 90, to = 91),
+        AutoMigration(from = 91, to = 92)
     ]
 )
 abstract class AppDatabase : RoomDatabase() {
@@ -164,6 +169,8 @@ abstract class AppDatabase : RoomDatabase() {
     abstract val homepageModuleDao: HomepageModuleDao
     abstract val homepageCustomSetDao: HomepageCustomSetDao
     abstract val highlightRuleDao: HighlightRuleDao
+    abstract val highlightTagRuleDao: HighlightTagRuleDao
+    abstract val tagGroupRuleDao: TagGroupRuleDao
 
     companion object {
 
@@ -237,6 +244,20 @@ abstract class AppDatabase : RoomDatabase() {
                 """.trimIndent()
                 db.execSQL(insertGroupReadFinished)
                 @Language("sql")
+                val insertGroupReadFinishedUpdate = """
+                    insert into book_groups(groupId, groupName, 'order', show) 
+                    select ${BookGroup.IdReadFinishedUpdate}, '连载已读', -27, 1
+                    where not exists (select * from book_groups where groupId = ${BookGroup.IdReadFinishedUpdate})
+                """.trimIndent()
+                db.execSQL(insertGroupReadFinishedUpdate)
+                @Language("sql")
+                val insertGroupReadFinishedComplete = """
+                    insert into book_groups(groupId, groupName, 'order', show) 
+                    select ${BookGroup.IdReadFinishedComplete}, '完本已读', -26, 1
+                    where not exists (select * from book_groups where groupId = ${BookGroup.IdReadFinishedComplete})
+                """.trimIndent()
+                db.execSQL(insertGroupReadFinishedComplete)
+                @Language("sql")
                 val insertBookGroupNetNoneGroupSql = """
                     insert into book_groups(groupId, groupName, 'order', show) 
                     select ${BookGroup.IdNetNone}, '网络未分组', -7, 1

+ 119 - 0
app/src/main/java/io/legado/app/data/dao/BookDao.kt

@@ -48,6 +48,8 @@ interface BookDao {
             BookGroup.IdUnread -> flowUnread()
             BookGroup.IdReading -> flowReading()
             BookGroup.IdReadFinished -> flowReadFinished()
+            BookGroup.IdReadFinishedUpdate -> flowReadFinishedUpdate()
+            BookGroup.IdReadFinishedComplete -> flowReadFinishedComplete()
             else -> flowByUserGroup(groupId)
         }.map { list ->
             list.filterNot { it.isNotShelf }
@@ -68,6 +70,8 @@ interface BookDao {
             BookGroup.IdUnread -> flowBookShelfUnread()
             BookGroup.IdReading -> flowBookShelfReading()
             BookGroup.IdReadFinished -> flowBookShelfReadFinished()
+            BookGroup.IdReadFinishedUpdate -> flowBookShelfReadFinishedUpdate()
+            BookGroup.IdReadFinishedComplete -> flowBookShelfReadFinishedComplete()
             else -> flowBookShelfByUserGroup(groupId)
         }.map { list ->
             list.filterNot { it.isNotShelf }
@@ -123,6 +127,9 @@ interface BookDao {
     @Query("SELECT * FROM books order by durChapterTime desc")
     fun flowAll(): Flow<List<Book>>
 
+    @Query("SELECT * FROM books")
+    suspend fun getAll(): List<Book>
+
     @Query(
         """
     SELECT 
@@ -485,6 +492,80 @@ interface BookDao {
     )
     fun flowBookShelfReadFinished(): Flow<List<BookShelfItem>>
 
+    @Query(
+        """SELECT * FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 1"""
+    )
+    fun flowReadFinishedUpdate(): Flow<List<Book>>
+
+    @Query(
+        """
+        SELECT 
+            bookUrl,
+            name,
+            author,
+            origin,
+            originName,
+            coverUrl,
+            customCoverUrl,
+            durChapterTitle,
+            durChapterTime,
+            durChapterPos,
+            latestChapterTitle,
+            latestChapterTime,
+            lastCheckCount,
+            totalChapterNum,
+            durChapterIndex,
+            type,
+            `group`,
+            `order`,
+            canUpdate,
+            ifnull(customIntro, intro) as intro,
+            kind,
+            wordCount
+        FROM books 
+        WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 1
+        AND $PUBLIC_BOOK_FILTER
+        """
+    )
+    fun flowBookShelfReadFinishedUpdate(): Flow<List<BookShelfItem>>
+
+    @Query(
+        """SELECT * FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 0"""
+    )
+    fun flowReadFinishedComplete(): Flow<List<Book>>
+
+    @Query(
+        """
+        SELECT 
+            bookUrl,
+            name,
+            author,
+            origin,
+            originName,
+            coverUrl,
+            customCoverUrl,
+            durChapterTitle,
+            durChapterTime,
+            durChapterPos,
+            latestChapterTitle,
+            latestChapterTime,
+            lastCheckCount,
+            totalChapterNum,
+            durChapterIndex,
+            type,
+            `group`,
+            `order`,
+            canUpdate,
+            ifnull(customIntro, intro) as intro,
+            kind,
+            wordCount
+        FROM books 
+        WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 0
+        AND $PUBLIC_BOOK_FILTER
+        """
+    )
+    fun flowBookShelfReadFinishedComplete(): Flow<List<BookShelfItem>>
+
     @Query("""SELECT * FROM books WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1""")
     fun flowReading(): Flow<List<Book>>
 
@@ -728,6 +809,8 @@ interface BookDao {
         UNION ALL SELECT ${BookGroup.IdUnread}, COUNT(*) FROM books WHERE durChapterIndex = 0 AND durChapterPos = 0 AND $PUBLIC_BOOK_FILTER
         UNION ALL SELECT ${BookGroup.IdReading}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex > 0 AND durChapterIndex < totalChapterNum - 1 AND $PUBLIC_BOOK_FILTER
         UNION ALL SELECT ${BookGroup.IdReadFinished}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND $PUBLIC_BOOK_FILTER
+        UNION ALL SELECT ${BookGroup.IdReadFinishedUpdate}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 1 AND $PUBLIC_BOOK_FILTER
+        UNION ALL SELECT ${BookGroup.IdReadFinishedComplete}, COUNT(*) FROM books WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 0 AND $PUBLIC_BOOK_FILTER
         """
     )
     fun flowSystemGroupCounts(): Flow<List<GroupBookCount>>
@@ -755,6 +838,8 @@ interface BookDao {
             BookGroup.IdUnread -> flowBookShelfUnreadPreview()
             BookGroup.IdReading -> flowBookShelfReadingPreview()
             BookGroup.IdReadFinished -> flowBookShelfReadFinishedPreview()
+            BookGroup.IdReadFinishedUpdate -> flowBookShelfReadFinishedUpdatePreview()
+            BookGroup.IdReadFinishedComplete -> flowBookShelfReadFinishedCompletePreview()
             else -> flowBookShelfPreviewByUserGroup(groupId)
         }.map { list ->
             list.filterNot { it.isNotShelf }
@@ -968,6 +1053,40 @@ interface BookDao {
     )
     fun flowBookShelfReadFinishedPreview(): Flow<List<BookShelfItem>>
 
+    @Query(
+        """
+        SELECT bookUrl, name, author, origin, originName,
+            coverUrl, customCoverUrl, durChapterTitle, durChapterTime,
+            durChapterPos, latestChapterTitle, latestChapterTime,
+            lastCheckCount, totalChapterNum, durChapterIndex,
+            type, `group`, `order`, canUpdate,
+            ifnull(customIntro, intro) as intro, kind, wordCount
+        FROM books
+        WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 1
+            AND $PUBLIC_BOOK_FILTER
+        ORDER BY durChapterTime DESC
+        LIMIT 10
+        """
+    )
+    fun flowBookShelfReadFinishedUpdatePreview(): Flow<List<BookShelfItem>>
+
+    @Query(
+        """
+        SELECT bookUrl, name, author, origin, originName,
+            coverUrl, customCoverUrl, durChapterTitle, durChapterTime,
+            durChapterPos, latestChapterTitle, latestChapterTime,
+            lastCheckCount, totalChapterNum, durChapterIndex,
+            type, `group`, `order`, canUpdate,
+            ifnull(customIntro, intro) as intro, kind, wordCount
+        FROM books
+        WHERE totalChapterNum > 0 AND durChapterIndex >= totalChapterNum - 1 AND canUpdate = 0
+            AND $PUBLIC_BOOK_FILTER
+        ORDER BY durChapterTime DESC
+        LIMIT 10
+        """
+    )
+    fun flowBookShelfReadFinishedCompletePreview(): Flow<List<BookShelfItem>>
+
     @Query(
         """
         SELECT bookUrl, name, author, origin, originName,

+ 14 - 0
app/src/main/java/io/legado/app/data/dao/BookGroupDao.kt

@@ -80,6 +80,20 @@ interface BookGroupDao {
             AND durChapterPos != 0
             AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
         ))
+        or (groupId = ${BookGroup.IdReadFinishedUpdate} and exists (
+            SELECT 1 FROM books 
+            WHERE totalChapterNum > 0 
+            AND durChapterIndex >= totalChapterNum - 1
+            AND canUpdate = 1
+            AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
+        ))
+        or (groupId = ${BookGroup.IdReadFinishedComplete} and exists (
+            SELECT 1 FROM books 
+            WHERE totalChapterNum > 0 
+            AND durChapterIndex >= totalChapterNum - 1
+            AND canUpdate = 0
+            AND (`group` = 0 or (const.sumPrivateGroupId & `group`) = 0)
+        ))
         
         or (groupId = ${BookGroup.IdError} and exists (
             select 1 from books

+ 4 - 0
app/src/main/java/io/legado/app/data/entities/BookGroup.kt

@@ -41,6 +41,8 @@ data class BookGroup(
         const val IdReading = -20L
         const val IdUnread = -21L
         const val IdReadFinished = -22L
+        const val IdReadFinishedUpdate = -23L
+        const val IdReadFinishedComplete = -24L
     }
 
     data class GroupNameInfo(
@@ -61,6 +63,8 @@ data class BookGroup(
             IdReading -> GroupNameInfo(groupName, context.getString(R.string.is_reading))
             IdUnread -> GroupNameInfo(groupName, context.getString(R.string.is_unread))
             IdReadFinished -> GroupNameInfo(groupName, context.getString(R.string.is_read_finished))
+            IdReadFinishedUpdate -> GroupNameInfo(groupName, context.getString(R.string.is_read_finished_update))
+            IdReadFinishedComplete -> GroupNameInfo(groupName, context.getString(R.string.is_read_finished_complete))
             else -> GroupNameInfo(groupName)
         }
     }

+ 37 - 0
app/src/main/res/values-zh-rCN/strings.xml

@@ -660,6 +660,7 @@
     <string name="footer_font_size">页脚字号</string>
     <string name="select_image">选择图片</string>
     <string name="group_manage">分组管理</string>
+    <string name="group_add">新建分组</string>
     <string name="group_select">分组选择</string>
     <string name="group_edit">编辑分组</string>
     <string name="move_to_group">移入分组</string>
@@ -1670,6 +1671,8 @@
     <string name="is_reading">在读</string>
     <string name="is_unread">未读</string>
     <string name="is_read_finished">已读</string>
+    <string name="is_read_finished_update">连载已读</string>
+    <string name="is_read_finished_complete">完本已读</string>
     <string name="manga">漫画</string>
     <string name="noval">小说</string>
     <string name="cover_show_shadow">显示字体阴影</string>
@@ -1947,4 +1950,38 @@
     <string name="eye_protection_schedule_summary">仅在配置的时间段内生效</string>
     <string name="eye_protection_start_time">开始时间</string>
     <string name="eye_protection_end_time">结束时间</string>
+
+    <!-- 标签规则 -->
+    <string name="highlight_tag_config">标签规则</string>
+    <string name="import_highlight_tag_rule">导入标签规则</string>
+    <string name="highlight_tag_title">标题</string>
+    <string name="highlight_tag_pattern">匹配规则</string>
+    <string name="highlight_tag_empty_hint">暂无醒目标签规则。添加规则可在书籍信息页面突出显示特定标签。</string>
+    <string name="highlight_tag_add_rule">添加规则</string>
+    <string name="highlight_tag_edit_rule">编辑规则</string>
+    <string name="highlight_tag_title_hint">标题(可选)</string>
+    <string name="highlight_tag_pattern_hint">正则表达式(如 (\\d+)字)</string>
+    <string name="highlight_tag_display_mode">显示模式</string>
+    <string name="highlight_tag_mode_horizontal">水平</string>
+    <string name="highlight_tag_mode_vertical">竖向</string>
+    <string name="highlight_tag_test_area">测试</string>
+    <string name="highlight_tag_test_input_hint">输入测试文本</string>
+    <string name="highlight_tag_test_button">测试匹配</string>
+    <string name="highlight_tag_test_match">匹配:%1$s</string>
+    <string name="highlight_tag_test_match_vertical">匹配:%1$s | %2$s</string>
+    <string name="highlight_tag_test_no_match">未匹配</string>
+    <string name="highlight_tag_test_error">错误:%1$s</string>
+
+    <!-- 标签分组规则 -->
+    <string name="tag_group_tab_highlight">醒目标签</string>
+    <string name="tag_group_tab_group">标签分组</string>
+    <string name="tag_group_add_rule">新建标签分组</string>
+    <string name="tag_group_edit_rule">编辑分组规则</string>
+    <string name="tag_group_name">分组名称</string>
+    <string name="tag_group_pattern">匹配规则(匹配书籍标签)</string>
+    <string name="tag_group_empty_hint">暂无标签分组规则。添加规则可根据书籍标签自动分组。</string>
+    <string name="tag_group_sync">同步标签分组</string>
+    <string name="tag_group_rules">标签分组规则</string>
+    <string name="tag_group_sync_complete">分组同步完成</string>
+    <string name="import_tag_group_rule">导入分组规则</string>
 </resources>

+ 37 - 0
app/src/main/res/values/strings.xml

@@ -686,6 +686,7 @@
     <string name="footer_font_size">Footer Font Size</string>
     <string name="select_image">Select a picture</string>
     <string name="group_manage">Group Management</string>
+    <string name="group_add">New Group</string>
     <string name="group_select">Group selection</string>
     <string name="group_edit">Group editing</string>
     <string name="move_to_group">Move to group</string>
@@ -1707,6 +1708,8 @@
     <string name="is_reading">Reading</string>
     <string name="is_unread">Unread</string>
     <string name="is_read_finished">Finished</string>
+    <string name="is_read_finished_update">Finished (Serial)</string>
+    <string name="is_read_finished_complete">Finished (Completed)</string>
     <string name="manga">Manga</string>
     <string name="noval">Novel</string>
     <string name="cover_show_shadow">Show Font Shadow</string>
@@ -1956,4 +1959,38 @@
     <string name="eye_protection_schedule_summary">Only apply during the configured time range</string>
     <string name="eye_protection_start_time">Start Time</string>
     <string name="eye_protection_end_time">End Time</string>
+
+    <!-- Tag Rules -->
+    <string name="highlight_tag_config">Tag Rules</string>
+    <string name="import_highlight_tag_rule">Import Tag Rules</string>
+    <string name="highlight_tag_title">Title</string>
+    <string name="highlight_tag_pattern">Pattern</string>
+    <string name="highlight_tag_empty_hint">No highlight tag rules configured. Add rules to highlight specific tags on the book info screen.</string>
+    <string name="highlight_tag_add_rule">Add Rule</string>
+    <string name="highlight_tag_edit_rule">Edit Rule</string>
+    <string name="highlight_tag_title_hint">Title (optional)</string>
+    <string name="highlight_tag_pattern_hint">Regex pattern (e.g. (\\d+)字)</string>
+    <string name="highlight_tag_display_mode">Display Mode</string>
+    <string name="highlight_tag_mode_horizontal">Horizontal</string>
+    <string name="highlight_tag_mode_vertical">Vertical</string>
+    <string name="highlight_tag_test_area">Test</string>
+    <string name="highlight_tag_test_input_hint">Enter test text</string>
+    <string name="highlight_tag_test_button">Test Match</string>
+    <string name="highlight_tag_test_match">Matched: %1$s</string>
+    <string name="highlight_tag_test_match_vertical">Matched: %1$s | %2$s</string>
+    <string name="highlight_tag_test_no_match">No match</string>
+    <string name="highlight_tag_test_error">Error: %1$s</string>
+
+    <!-- Tag Group Rules -->
+    <string name="tag_group_tab_highlight">Highlight</string>
+    <string name="tag_group_tab_group">Group</string>
+    <string name="tag_group_add_rule">New Tag Group</string>
+    <string name="tag_group_edit_rule">Edit Group Rule</string>
+    <string name="tag_group_name">Group Name</string>
+    <string name="tag_group_pattern">Pattern (matches kind tags)</string>
+    <string name="tag_group_empty_hint">No tag group rules configured. Add rules to auto-group books by their kind tags.</string>
+    <string name="tag_group_sync">Sync Tag Groups</string>
+    <string name="tag_group_rules">Tag Group Rules</string>
+    <string name="tag_group_sync_complete">Group sync complete</string>
+    <string name="import_tag_group_rule">Import Tag Group Rules</string>
 </resources>