From 6b55311ccc29586d18686d20ede8128f74423fa1 Mon Sep 17 00:00:00 2001 From: Horis <8674809+821938089@users.noreply.github.com> Date: Mon, 27 Oct 2025 11:19:26 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/constant/AppPattern.kt | 1 + .../main/java/io/legado/app/help/AppWebDav.kt | 43 +++++++++++-------- .../io/legado/app/help/book/BookExtensions.kt | 3 +- .../java/io/legado/app/help/storage/Backup.kt | 19 ++++++-- .../main/java/io/legado/app/model/ReadBook.kt | 7 +-- .../java/io/legado/app/model/ReadManga.kt | 5 ++- .../app/ui/book/read/ReadBookActivity.kt | 2 +- .../io/legado/app/utils/StringExtensions.kt | 4 ++ gradle/libs.versions.toml | 2 +- 9 files changed, 56 insertions(+), 30 deletions(-) diff --git a/app/src/main/java/io/legado/app/constant/AppPattern.kt b/app/src/main/java/io/legado/app/constant/AppPattern.kt index 20d9ddb4e..b38cc313c 100644 --- a/app/src/main/java/io/legado/app/constant/AppPattern.kt +++ b/app/src/main/java/io/legado/app/constant/AppPattern.kt @@ -17,6 +17,7 @@ object AppPattern { val nameRegex = Regex("\\s+作\\s*者.*|\\s+\\S+\\s+著") val authorRegex = Regex("^\\s*作\\s*者[::\\s]+|\\s+著") val fileNameRegex = Regex("[\\\\/:*?\"<>|.]") + val fileNameRegex2 = Regex("[\\\\/:*?\"<>|]") val splitGroupRegex = Regex("[,;,;]") val titleNumPattern: Pattern = Pattern.compile("(第)(.+?)(章)") diff --git a/app/src/main/java/io/legado/app/help/AppWebDav.kt b/app/src/main/java/io/legado/app/help/AppWebDav.kt index 957da1540..fa71a6fee 100644 --- a/app/src/main/java/io/legado/app/help/AppWebDav.kt +++ b/app/src/main/java/io/legado/app/help/AppWebDav.kt @@ -25,13 +25,14 @@ import io.legado.app.utils.compress.ZipUtils import io.legado.app.utils.fromJsonObject import io.legado.app.utils.getPrefString import io.legado.app.utils.isJson +import io.legado.app.utils.normalizeFileName import io.legado.app.utils.removePref import io.legado.app.utils.toastOnUi +import kotlinx.coroutines.currentCoroutineContext import kotlinx.coroutines.ensureActive import kotlinx.coroutines.runBlocking import splitties.init.appCtx import java.io.File -import kotlin.coroutines.coroutineContext /** * webDav初始化会访问网络,不要放到主线程 @@ -219,7 +220,7 @@ object AppWebDav { WebDav(putUrl, it).upload(byteArray, "text/plain") } } catch (e: Exception) { - coroutineContext.ensureActive() + currentCoroutineContext().ensureActive() AppLog.put("WebDav导出失败\n${e.localizedMessage}", e, true) } } @@ -233,12 +234,16 @@ object AppWebDav { WebDav(putUrl, it).upload(uri, "text/plain") } } catch (e: Exception) { - coroutineContext.ensureActive() + currentCoroutineContext().ensureActive() AppLog.put("WebDav导出失败\n${e.localizedMessage}", e, true) } } - suspend fun uploadBookProgress(book: Book) { + suspend fun uploadBookProgress( + book: Book, + toast: Boolean = false, + onSuccess: (() -> Unit)? = null + ) { val authorization = authorization ?: return if (!AppConfig.syncBookProgress) return if (!NetworkUtils.isAvailable()) return @@ -248,9 +253,10 @@ object AppWebDav { val url = getProgressUrl(book.name, book.author) WebDav(url, authorization).upload(json.toByteArray(), "application/json") book.syncTime = System.currentTimeMillis() + onSuccess?.invoke() } catch (e: Exception) { - coroutineContext.ensureActive() - AppLog.put("上传进度失败\n${e.localizedMessage}", e) + currentCoroutineContext().ensureActive() + AppLog.put("上传进度失败\n${e.localizedMessage}", e, toast) } } @@ -264,7 +270,7 @@ object AppWebDav { WebDav(url, authorization).upload(json.toByteArray(), "application/json") onSuccess?.invoke() } catch (e: Exception) { - coroutineContext.ensureActive() + currentCoroutineContext().ensureActive() AppLog.put("上传进度失败\n${e.localizedMessage}", e) } } @@ -274,26 +280,25 @@ object AppWebDav { } private fun getProgressFileName(name: String, author: String): String { - return UrlUtil.replaceReservedChar("${name}_${author}") + ".json" + return UrlUtil.replaceReservedChar("${name}_${author}".normalizeFileName()) + ".json" } /** * 获取书籍进度 */ suspend fun getBookProgress(book: Book): BookProgress? { - authorization?.let { - val url = getProgressUrl(book.name, book.author) - kotlin.runCatching { - WebDav(url, it).download().let { byteArray -> - val json = String(byteArray) - if (json.isJson()) { - return GSON.fromJsonObject(json).getOrNull() - } + val url = getProgressUrl(book.name, book.author) + kotlin.runCatching { + val authorization = authorization ?: return null + WebDav(url, authorization).download().let { byteArray -> + val json = String(byteArray) + if (json.isJson()) { + return GSON.fromJsonObject(json).getOrNull() } - }.onFailure { - coroutineContext.ensureActive() - AppLog.put("获取书籍进度失败\n${it.localizedMessage}", it) } + }.onFailure { + currentCoroutineContext().ensureActive() + AppLog.put("获取书籍进度失败\n${it.localizedMessage}", it) } return null } 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 88a51cdd4..2e7f94361 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 @@ -24,6 +24,7 @@ import io.legado.app.utils.exists import io.legado.app.utils.find import io.legado.app.utils.inputStream import io.legado.app.utils.isUri +import io.legado.app.utils.normalizeFileName import io.legado.app.utils.toastOnUi import splitties.init.appCtx import java.io.File @@ -346,7 +347,7 @@ fun Book.getExportFileName( RhinoScriptEngine.eval(jsStr, bindings).toString() + "." + suffix }.onFailure { AppLog.put("导出书名规则错误,使用默认规则\n${it.localizedMessage}", it) - }.getOrDefault(default) + }.getOrDefault(default).normalizeFileName() } // 根据当前日期计算章节总数 diff --git a/app/src/main/java/io/legado/app/help/storage/Backup.kt b/app/src/main/java/io/legado/app/help/storage/Backup.kt index a60c6a231..f604c974b 100644 --- a/app/src/main/java/io/legado/app/help/storage/Backup.kt +++ b/app/src/main/java/io/legado/app/help/storage/Backup.kt @@ -14,8 +14,20 @@ import io.legado.app.help.config.LocalConfig import io.legado.app.help.config.ReadBookConfig import io.legado.app.help.config.ThemeConfig import io.legado.app.help.coroutine.Coroutine -import io.legado.app.utils.* +import io.legado.app.utils.FileUtils +import io.legado.app.utils.GSON +import io.legado.app.utils.LogUtils import io.legado.app.utils.compress.ZipUtils +import io.legado.app.utils.createFolderIfNotExist +import io.legado.app.utils.defaultSharedPreferences +import io.legado.app.utils.externalFiles +import io.legado.app.utils.getFile +import io.legado.app.utils.getSharedPreferences +import io.legado.app.utils.isContentScheme +import io.legado.app.utils.normalizeFileName +import io.legado.app.utils.openOutputStream +import io.legado.app.utils.outputStream +import io.legado.app.utils.writeToOutputStream import kotlinx.coroutines.Dispatchers.IO import kotlinx.coroutines.ensureActive import kotlinx.coroutines.sync.Mutex @@ -26,7 +38,8 @@ import java.io.File import java.io.FileInputStream import java.io.FileOutputStream import java.text.SimpleDateFormat -import java.util.* +import java.util.Date +import java.util.Locale import java.util.concurrent.TimeUnit import kotlin.coroutines.coroutineContext @@ -77,7 +90,7 @@ object Backup { "backup${backupDate}-${deviceName}.zip" } else { "backup${backupDate}.zip" - } + }.normalizeFileName() } private fun shouldBackup(): Boolean { diff --git a/app/src/main/java/io/legado/app/model/ReadBook.kt b/app/src/main/java/io/legado/app/model/ReadBook.kt index 18a5a9335..70396d6e4 100644 --- a/app/src/main/java/io/legado/app/model/ReadBook.kt +++ b/app/src/main/java/io/legado/app/model/ReadBook.kt @@ -224,13 +224,14 @@ object ReadBook : CoroutineScope by MainScope() { nextTextChapter?.clearSearchResult() } - fun uploadProgress(successAction: (() -> Unit)? = null) { + fun uploadProgress(toast: Boolean = false, successAction: (() -> Unit)? = null) { book?.let { launch(IO) { - AppWebDav.uploadBookProgress(it) + AppWebDav.uploadBookProgress(it, toast) { + successAction?.invoke() + } ensureActive() it.update() - successAction?.invoke() } } } diff --git a/app/src/main/java/io/legado/app/model/ReadManga.kt b/app/src/main/java/io/legado/app/model/ReadManga.kt index 07153a936..613448077 100644 --- a/app/src/main/java/io/legado/app/model/ReadManga.kt +++ b/app/src/main/java/io/legado/app/model/ReadManga.kt @@ -482,10 +482,11 @@ object ReadManga : CoroutineScope by MainScope() { fun uploadProgress(successAction: (() -> Unit)? = null) { book?.let { launch(IO) { - AppWebDav.uploadBookProgress(it) + AppWebDav.uploadBookProgress(it) { + successAction?.invoke() + } ensureActive() it.update() - successAction?.invoke() } } } diff --git a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt index 3f19fde3c..9ac88827e 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/ReadBookActivity.kt @@ -598,7 +598,7 @@ class ReadBookActivity : BaseReadBookActivity(), } R.id.menu_cover_progress -> ReadBook.book?.let { - ReadBook.uploadProgress { toastOnUi(R.string.upload_book_success) } + ReadBook.uploadProgress(true) { toastOnUi(R.string.upload_book_success) } } R.id.menu_same_title_removed -> { diff --git a/app/src/main/java/io/legado/app/utils/StringExtensions.kt b/app/src/main/java/io/legado/app/utils/StringExtensions.kt index 483ef96e3..5de0b9086 100644 --- a/app/src/main/java/io/legado/app/utils/StringExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/StringExtensions.kt @@ -140,3 +140,7 @@ fun String.escapeRegex(): String { } fun String.encodeURI(): String = URLEncodeUtil.encodeQuery(this) + +fun String.normalizeFileName(): String { + return replace(AppPattern.fileNameRegex2, "_") +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0b7356f85..cf214dafa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ viewpager2 = "1.0.0" webkit = "1.13.0" collection = "1.5.0" -zxingLite = "3.2.0" +zxingLite = "3.3.0" [libraries]