Преглед изворни кода

[修复] bookUri 发生更改后, 小说裂变成两个的 bug

ryan пре 8 месеци
родитељ
комит
cb236b623c

+ 50 - 6
app/src/main/java/io/legado/app/help/book/BookExtensions.kt

@@ -121,6 +121,29 @@ fun Book.contains(word: String?): Boolean {
             || intro?.contains(word) == true
             || intro?.contains(word) == true
 }
 }
 
 
+/**
+ * 仅在目标bookUrl未被其他书占用,或判定为同一本书时,允许迁移主键。
+ */
+fun Book.canSafelyRebindTo(newBookUrl: String): Boolean {
+    if (newBookUrl == bookUrl) return true
+    val targetBook = appDb.bookDao.getBook(newBookUrl) ?: return true
+    if (targetBook.bookUrl == bookUrl) return true
+    val sameOriginName = originName.isNotBlank() && originName == targetBook.originName
+    val sameNameAuthor = name.isNotBlank() && author.isNotBlank()
+            && name == targetBook.name && author == targetBook.author
+    val sameOrigin = origin.isNotBlank() && origin == targetBook.origin
+    val canMerge = sameOriginName && (sameNameAuthor || sameOrigin)
+    if (!canMerge) {
+        AppLog.put(
+            "书籍重定位冲突,已跳过迁移\n" +
+                    "old=$bookUrl\nnew=$newBookUrl\n" +
+                    "oldName=$name oldAuthor=$author oldOriginName=$originName\n" +
+                    "targetName=${targetBook.name} targetAuthor=${targetBook.author} targetOriginName=${targetBook.originName}"
+        )
+    }
+    return canMerge
+}
+
 private val localUriCache by lazy {
 private val localUriCache by lazy {
     ConcurrentHashMap<String, Uri>()
     ConcurrentHashMap<String, Uri>()
 }
 }
@@ -158,9 +181,19 @@ fun Book.getLocalUri(): Uri {
             val fileDoc = treeFileDoc.find(originName, 5, 100)
             val fileDoc = treeFileDoc.find(originName, 5, 100)
             if (fileDoc != null) {
             if (fileDoc != null) {
                 localUriCache[bookUrl] = fileDoc.uri
                 localUriCache[bookUrl] = fileDoc.uri
-                //更新bookUrl 重启不用再找一遍
-                bookUrl = fileDoc.toString()
-                save()
+                //更新bookUrl时要迁移主键,避免save()按新bookUrl插入重复书籍
+                val oldBook = copy()
+                val newBookUrl = fileDoc.toString()
+                if (!oldBook.canSafelyRebindTo(newBookUrl)) {
+                    return fileDoc.uri
+                }
+                bookUrl = newBookUrl
+                if (oldBook.bookUrl == bookUrl) {
+                    save()
+                } else {
+                    appDb.bookDao.replace(oldBook, this)
+                    BookHelp.updateCacheFolder(oldBook, this)
+                }
                 return fileDoc.uri
                 return fileDoc.uri
             }
             }
         }
         }
@@ -177,8 +210,19 @@ fun Book.getLocalUri(): Uri {
         val fileDoc = treeFileDoc.find(originName, 5, 100)
         val fileDoc = treeFileDoc.find(originName, 5, 100)
         if (fileDoc != null) {
         if (fileDoc != null) {
             localUriCache[bookUrl] = fileDoc.uri
             localUriCache[bookUrl] = fileDoc.uri
-            bookUrl = fileDoc.toString()
-            save()
+            //更新bookUrl时要迁移主键,避免save()按新bookUrl插入重复书籍
+            val oldBook = copy()
+            val newBookUrl = fileDoc.toString()
+            if (!oldBook.canSafelyRebindTo(newBookUrl)) {
+                return fileDoc.uri
+            }
+            bookUrl = newBookUrl
+            if (oldBook.bookUrl == bookUrl) {
+                save()
+            } else {
+                appDb.bookDao.replace(oldBook, this)
+                BookHelp.updateCacheFolder(oldBook, this)
+            }
             return fileDoc.uri
             return fileDoc.uri
         }
         }
     }
     }
@@ -438,4 +482,4 @@ fun tryParesExportFileName(jsStr: String): Boolean {
         RhinoScriptEngine.eval(jsStr, bindings)
         RhinoScriptEngine.eval(jsStr, bindings)
         true
         true
     }.getOrDefault(false)
     }.getOrDefault(false)
-}
+}

+ 17 - 2
app/src/main/java/io/legado/app/model/localBook/LocalBook.kt

@@ -23,6 +23,8 @@ import io.legado.app.help.book.BookHelp
 import io.legado.app.help.book.ContentProcessor
 import io.legado.app.help.book.ContentProcessor
 import io.legado.app.help.book.addType
 import io.legado.app.help.book.addType
 import io.legado.app.help.book.archiveName
 import io.legado.app.help.book.archiveName
+import io.legado.app.help.book.cacheLocalUri
+import io.legado.app.help.book.canSafelyRebindTo
 import io.legado.app.help.book.getArchiveUri
 import io.legado.app.help.book.getArchiveUri
 import io.legado.app.help.book.getLocalUri
 import io.legado.app.help.book.getLocalUri
 import io.legado.app.help.book.getRemoteUrl
 import io.legado.app.help.book.getRemoteUrl
@@ -37,6 +39,7 @@ import io.legado.app.help.config.AppConfig
 import io.legado.app.lib.webdav.WebDav
 import io.legado.app.lib.webdav.WebDav
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.lib.webdav.WebDavException
 import io.legado.app.model.analyzeRule.AnalyzeUrl
 import io.legado.app.model.analyzeRule.AnalyzeUrl
+import io.legado.app.model.analyzeRule.CustomUrl
 import io.legado.app.utils.ArchiveUtils
 import io.legado.app.utils.ArchiveUtils
 import io.legado.app.utils.FileDoc
 import io.legado.app.utils.FileDoc
 import io.legado.app.utils.FileUtils
 import io.legado.app.utils.FileUtils
@@ -501,9 +504,21 @@ object LocalBook {
                     localBook.bookUrl = newBook.bookUrl
                     localBook.bookUrl = newBook.bookUrl
                 } else {
                 } else {
                     // txt epub pdf umd
                     // txt epub pdf umd
+                    val oldBook = localBook.copy()
                     val fileUri = saveBookFile(it, localBook.originName)
                     val fileUri = saveBookFile(it, localBook.originName)
-                    localBook.bookUrl = FileDoc.fromUri(fileUri, false).toString()
-                    localBook.save()
+                    val newBookUrl = FileDoc.fromUri(fileUri, false).toString()
+                    if (!oldBook.canSafelyRebindTo(newBookUrl)) {
+                        localBook.cacheLocalUri(fileUri)
+                        return true
+                    }
+                    localBook.bookUrl = newBookUrl
+                    localBook.origin = BookType.webDavTag + CustomUrl(webDavUrl).toString()
+                    if (oldBook.bookUrl == localBook.bookUrl) {
+                        localBook.save()
+                    } else {
+                        appDb.bookDao.replace(oldBook, localBook)
+                        BookHelp.updateCacheFolder(oldBook, localBook)
+                    }
                 }
                 }
             }
             }
             return true
             return true