Prechádzať zdrojové kódy

Tweak saved filename byte size limiting logic

Based on comment from https://github.com/inorichi/tachiyomi/commit/6940ad3fd9d37d81988c9f42c26e5ada0c178d8a
arkon 5 rokov pred
rodič
commit
1c978f64b1

+ 5 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -21,6 +21,8 @@ import eu.kanade.tachiyomi.ui.reader.loader.DownloadPageLoader
 import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
 import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
+import eu.kanade.tachiyomi.util.lang.byteSize
+import eu.kanade.tachiyomi.util.lang.takeBytes
 import eu.kanade.tachiyomi.util.storage.DiskUtil
 import eu.kanade.tachiyomi.util.system.ImageUtil
 import java.io.File
@@ -450,7 +452,7 @@ class ReaderPresenter(
         // Build destination file.
         val filenameSuffix = " - ${page.number}.${type.extension}"
         val filename = DiskUtil.buildValidFilename(
-                "${manga.title} - ${chapter.name}".take(MAX_FILE_NAME_LENGTH - filenameSuffix.length)
+                "${manga.title} - ${chapter.name}".takeBytes(MAX_FILE_NAME_BYTES - filenameSuffix.byteSize())
         ) + filenameSuffix
 
         val destFile = File(directory, filename)
@@ -641,7 +643,7 @@ class ReaderPresenter(
     }
 
     companion object {
-        // Safe max filename size is 255 bytes and 1 char = 2 bytes
-        private const val MAX_FILE_NAME_LENGTH = 127
+        // Safe theoretical max filename size is 255 bytes and 1 char = 2-4 bytes (UTF-8)
+        private const val MAX_FILE_NAME_BYTES = 250
     }
 }

+ 21 - 0
app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt

@@ -32,3 +32,24 @@ fun String.truncateCenter(count: Int, replacement: String = "..."): String {
 fun String.compareToCaseInsensitiveNaturalOrder(other: String): Int {
     return String.CASE_INSENSITIVE_ORDER.then(naturalOrder()).compare(this, other)
 }
+
+/**
+ * Returns the size of the string as the number of bytes.
+ */
+fun String.byteSize(): Int {
+    return toByteArray(Charsets.UTF_8).size
+}
+
+/**
+ * Returns a string containing the first [n] bytes from this string, or the entire string if this
+ * string is shorter.
+ */
+@UseExperimental(ExperimentalStdlibApi::class)
+fun String.takeBytes(n: Int): String {
+    val bytes = toByteArray(Charsets.UTF_8)
+    return if (bytes.size <= n) {
+        this
+    } else {
+        bytes.decodeToString(endIndex = n).replace("\uFFFD", "")
+    }
+}