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

fix: 修复备份恢复逻辑,补充遗漏实体的备份恢复

- 修复开启忽略本地书籍时恢复会误删设备本地书的问题,改为合并保留本地书
- BookGroup 恢复改为先删后插(replaceAll),避免残留旧分组
- 补充 HomepageModule、HomepageCustomSet、HighlightRule、HighlightTagRule、TagGroupRule 的备份恢复
- 各 DAO 新增 replaceAll 方法支持全量替换
HapeLee 4 месяцев назад
Родитель
Сommit
972306e263

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

@@ -148,6 +148,17 @@ interface BookGroupDao {
     @Insert(onConflict = OnConflictStrategy.REPLACE)
     fun insert(vararg bookGroup: BookGroup)
 
+    @androidx.room.Transaction
+    fun replaceAll(bookGroups: List<BookGroup>) {
+        deleteAll()
+        if (bookGroups.isNotEmpty()) {
+            insert(*bookGroups.toTypedArray())
+        }
+    }
+
+    @Query("DELETE FROM book_groups")
+    fun deleteAll()
+
     @Update
     fun update(vararg bookGroup: BookGroup)
 

+ 10 - 0
app/src/main/java/io/legado/app/data/dao/HighlightTagRuleDao.kt

@@ -36,4 +36,14 @@ interface HighlightTagRuleDao {
     @Query("DELETE FROM highlight_tag_rules")
     suspend fun deleteAll()
 
+    @Query("SELECT * FROM highlight_tag_rules ORDER BY `order` ASC")
+    fun getAll(): List<HighlightTagRule>
+
+    @androidx.room.Transaction
+    suspend fun replaceAll(rules: List<HighlightTagRule>) {
+        deleteAll()
+        if (rules.isNotEmpty()) {
+            insert(*rules.toTypedArray())
+        }
+    }
 }

+ 17 - 0
app/src/main/java/io/legado/app/data/dao/HomepageCustomSetDao.kt

@@ -32,4 +32,21 @@ interface HomepageCustomSetDao {
 
     @Query("DELETE FROM homepage_custom_sets WHERE id = :id")
     suspend fun delete(id: String)
+
+    @Query("SELECT * FROM homepage_custom_sets ORDER BY sortOrder ASC")
+    fun getAll(): List<HomepageCustomSet>
+
+    @Query("DELETE FROM homepage_custom_sets")
+    fun deleteAll()
+
+    @Insert(onConflict = OnConflictStrategy.REPLACE)
+    fun insertAll(sets: List<HomepageCustomSet>)
+
+    @androidx.room.Transaction
+    fun replaceAll(sets: List<HomepageCustomSet>) {
+        deleteAll()
+        if (sets.isNotEmpty()) {
+            insertAll(sets)
+        }
+    }
 }

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

@@ -50,4 +50,18 @@ interface HomepageModuleDao {
 
     @Query("SELECT * FROM homepage_modules ORDER BY sortOrder ASC")
     fun flowAll(): Flow<List<HomepageModule>>
+
+    @Query("SELECT * FROM homepage_modules ORDER BY sortOrder ASC")
+    fun getAll(): List<HomepageModule>
+
+    @Query("DELETE FROM homepage_modules")
+    fun deleteAll()
+
+    @androidx.room.Transaction
+    suspend fun replaceAll(modules: List<HomepageModule>) {
+        deleteAll()
+        if (modules.isNotEmpty()) {
+            upsertAll(modules)
+        }
+    }
 }

+ 8 - 0
app/src/main/java/io/legado/app/data/dao/TagGroupRuleDao.kt

@@ -41,4 +41,12 @@ interface TagGroupRuleDao {
 
     @Query("DELETE FROM tag_group_rules")
     suspend fun deleteAll()
+
+    @androidx.room.Transaction
+    suspend fun replaceAll(rules: List<TagGroupRule>) {
+        deleteAll()
+        if (rules.isNotEmpty()) {
+            insert(*rules.toTypedArray())
+        }
+    }
 }

+ 10 - 0
app/src/main/java/io/legado/app/help/storage/Backup.kt

@@ -74,6 +74,11 @@ object Backup {
             "httpTTS.json",
             "keyboardAssists.json",
             "dictRule.json",
+            "homepageModules.json",
+            "homepageCustomSets.json",
+            "highlightRule.json",
+            "highlightTagRule.json",
+            "tagGroupRule.json",
             "servers.json",
             DirectLinkUpload.ruleFileName,
             ReadBookConfig.configFileName,
@@ -148,6 +153,11 @@ object Backup {
         writeListToJson(appDb.httpTTSDao.all, "httpTTS.json", backupPath)
         writeListToJson(appDb.keyboardAssistsDao.all, "keyboardAssists.json", backupPath)
         writeListToJson(appDb.dictRuleDao.all, "dictRule.json", backupPath)
+        writeListToJson(appDb.homepageModuleDao.getAll(), "homepageModules.json", backupPath)
+        writeListToJson(appDb.homepageCustomSetDao.getAll(), "homepageCustomSets.json", backupPath)
+        writeListToJson(appDb.highlightRuleDao.getAll(), "highlightRule.json", backupPath)
+        writeListToJson(appDb.highlightTagRuleDao.getAll(), "highlightTagRule.json", backupPath)
+        writeListToJson(appDb.tagGroupRuleDao.getAll(), "tagGroupRule.json", backupPath)
         GSON.toJson(appDb.serverDao.all).let { json ->
             aes.runCatching {
                 encryptBase64(json)

+ 28 - 7
app/src/main/java/io/legado/app/help/storage/Restore.kt

@@ -16,6 +16,10 @@ import io.legado.app.data.entities.BookGroup
 import io.legado.app.data.entities.BookSource
 import io.legado.app.data.entities.Bookmark
 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.HomepageCustomSet
+import io.legado.app.data.entities.HomepageModule
 import io.legado.app.data.entities.HttpTTS
 import io.legado.app.data.entities.KeyboardAssist
 import io.legado.app.data.entities.ReplaceRule
@@ -24,6 +28,7 @@ import io.legado.app.data.entities.RssStar
 import io.legado.app.data.entities.RuleSub
 import io.legado.app.data.entities.SearchKeyword
 import io.legado.app.data.entities.Server
+import io.legado.app.data.entities.TagGroupRule
 import io.legado.app.data.entities.TxtTocRule
 import io.legado.app.data.entities.readRecord.ReadRecord
 import io.legado.app.data.entities.readRecord.ReadRecordDetail
@@ -117,10 +122,14 @@ object Restore : KoinComponent {
                     book.coverUrl = LocalBook.getCoverPath(book)
                 }
             val ignoreLocalBook = BackupConfig.ignoreLocalBook
-            val restoredBooks = it.filterNot { book ->
-                ignoreLocalBook && book.isLocal
+            if (ignoreLocalBook) {
+                val backupNonLocal = it.filterNot { book -> book.isLocal }
+                val existingLocal = appDb.bookDao.all.filter { book -> book.isLocal }
+                val mergedBooks = existingLocal + backupNonLocal
+                appDb.bookDao.replaceAll(mergedBooks)
+            } else {
+                appDb.bookDao.replaceAll(it)
             }
-            appDb.bookDao.replaceAll(restoredBooks)
         }
         fileToListT<Bookmark>(path, "bookmark.json")?.let {
             try {
@@ -129,10 +138,7 @@ object Restore : KoinComponent {
             }
         }
         fileToListT<BookGroup>(path, "bookGroup.json")?.let {
-            try {
-                appDb.bookGroupDao.insert(*it.toTypedArray())
-            } catch (_: SQLiteConstraintException) {
-            }
+            appDb.bookGroupDao.replaceAll(it)
         }
         fileToListT<BookSource>(path, "bookSource.json")?.let {
             try {
@@ -200,6 +206,21 @@ object Restore : KoinComponent {
             } catch (_: SQLiteConstraintException) {
             }
         }
+        fileToListT<HomepageModule>(path, "homepageModules.json")?.let {
+            appDb.homepageModuleDao.replaceAll(it)
+        }
+        fileToListT<HomepageCustomSet>(path, "homepageCustomSets.json")?.let {
+            appDb.homepageCustomSetDao.replaceAll(it)
+        }
+        fileToListT<HighlightRule>(path, "highlightRule.json")?.let {
+            appDb.highlightRuleDao.replaceAll(it)
+        }
+        fileToListT<HighlightTagRule>(path, "highlightTagRule.json")?.let {
+            appDb.highlightTagRuleDao.replaceAll(it)
+        }
+        fileToListT<TagGroupRule>(path, "tagGroupRule.json")?.let {
+            appDb.tagGroupRuleDao.replaceAll(it)
+        }
         fileToListT<ReadRecord>(path, "readRecord.json")?.let {
             it.forEach { readRecord ->
                 if (readRecord.deviceId != androidId) {