diff --git a/app/src/main/java/io/legado/app/help/book/BookExtensions.kt b/app/src/main/java/io/legado/app/help/book/BookExtensions.kt index 4523d1340..2e8ecea70 100644 --- a/app/src/main/java/io/legado/app/help/book/BookExtensions.kt +++ b/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 } +/** + * 仅在目标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 { ConcurrentHashMap() } @@ -158,9 +181,19 @@ fun Book.getLocalUri(): Uri { val fileDoc = treeFileDoc.find(originName, 5, 100) if (fileDoc != null) { 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 } } @@ -177,8 +210,19 @@ fun Book.getLocalUri(): Uri { val fileDoc = treeFileDoc.find(originName, 5, 100) if (fileDoc != null) { 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 } } @@ -438,4 +482,4 @@ fun tryParesExportFileName(jsStr: String): Boolean { RhinoScriptEngine.eval(jsStr, bindings) true }.getOrDefault(false) -} \ No newline at end of file +} diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index e95ef0de4..f14ae46ca 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/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.addType 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.getLocalUri 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.WebDavException 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.FileDoc import io.legado.app.utils.FileUtils @@ -501,9 +504,21 @@ object LocalBook { localBook.bookUrl = newBook.bookUrl } else { // txt epub pdf umd + val oldBook = localBook.copy() 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