Fix pages filename #151

pull/167/head
Koitharu 4 years ago
parent 23e7aa2aaa
commit b759f8d0a0
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.await
import org.koitharu.kotatsu.parsers.util.medianOrNull import org.koitharu.kotatsu.parsers.util.medianOrNull
import java.io.File
import java.io.InputStream import java.io.InputStream
import java.util.zip.ZipFile import java.util.zip.ZipFile
@ -59,6 +60,14 @@ object MangaUtils : KoinComponent {
} }
} }
suspend fun getImageMimeType(file: File): String? = runInterruptible(Dispatchers.IO) {
val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true
}
BitmapFactory.decodeFile(file.path, options)?.recycle()
options.outMimeType
}
private fun getBitmapSize(input: InputStream?): Size { private fun getBitmapSize(input: InputStream?): Size {
val options = BitmapFactory.Options().apply { val options = BitmapFactory.Options().apply {
inJustDecodeBounds = true inJustDecodeBounds = true

@ -2,19 +2,26 @@ package org.koitharu.kotatsu.reader.ui
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import android.webkit.MimeTypeMap
import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.ActivityResultLauncher
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okio.IOException import okio.IOException
import org.koitharu.kotatsu.base.domain.MangaUtils
import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.local.data.PagesCache
import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.util.toFileNameSafe
import org.koitharu.kotatsu.reader.domain.PageLoader import org.koitharu.kotatsu.reader.domain.PageLoader
import java.io.File
import kotlin.coroutines.Continuation import kotlin.coroutines.Continuation
import kotlin.coroutines.coroutineContext
import kotlin.coroutines.resume import kotlin.coroutines.resume
private const val MAX_FILENAME_LENGTH = 10
private const val EXTENSION_FALLBACK = "png"
class PageSaveHelper( class PageSaveHelper(
private val cache: PagesCache, private val cache: PagesCache,
context: Context, context: Context,
@ -28,21 +35,16 @@ class PageSaveHelper(
page: MangaPage, page: MangaPage,
saveLauncher: ActivityResultLauncher<String>, saveLauncher: ActivityResultLauncher<String>,
): Uri { ): Uri {
var pageFile = cache[page.url] val pageUrl = pageLoader.getPageUrl(page)
var fileName = pageFile?.name val pageFile = pageLoader.loadPage(page, force = false)
if (fileName == null) { val proposedName = getProposedFileName(pageUrl, pageFile)
fileName = pageLoader.getPageUrl(page).toHttpUrl().pathSegments.last() val destination = withContext(Dispatchers.Main) {
} suspendCancellableCoroutine<Uri> { cont ->
val cc = coroutineContext
val destination = suspendCancellableCoroutine<Uri> { cont ->
continuation = cont continuation = cont
Dispatchers.Main.dispatch(cc) { saveLauncher.launch(proposedName)
saveLauncher.launch(fileName) }.also {
}
}
continuation = null continuation = null
if (pageFile == null) { }
pageFile = pageLoader.loadPage(page, force = false)
} }
runInterruptible(Dispatchers.IO) { runInterruptible(Dispatchers.IO) {
contentResolver.openOutputStream(destination)?.use { output -> contentResolver.openOutputStream(destination)?.use { output ->
@ -57,4 +59,19 @@ class PageSaveHelper(
fun onActivityResult(uri: Uri): Boolean = continuation?.apply { fun onActivityResult(uri: Uri): Boolean = continuation?.apply {
resume(uri) resume(uri)
} != null } != null
private suspend fun getProposedFileName(url: String, file: File): String {
var name = url.toHttpUrl().pathSegments.last()
var extension = name.substringAfterLast('.', "")
name = name.substringBeforeLast('.')
if (extension.length !in 2..4) {
val mimeType = MangaUtils.getImageMimeType(file)
extension = if (mimeType != null) {
MimeTypeMap.getSingleton().getExtensionFromMimeType(mimeType) ?: EXTENSION_FALLBACK
} else {
EXTENSION_FALLBACK
}
}
return name.toFileNameSafe().take(MAX_FILENAME_LENGTH) + "." + extension
}
} }
Loading…
Cancel
Save