diff --git a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaUtils.kt b/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaUtils.kt index 09a970eee..03b0dd53b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaUtils.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/domain/MangaUtils.kt @@ -15,6 +15,7 @@ import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.util.await import org.koitharu.kotatsu.parsers.util.medianOrNull +import java.io.File import java.io.InputStream 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 { val options = BitmapFactory.Options().apply { inJustDecodeBounds = true diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt index a2d8f7ac5..3e19c7036 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/PageSaveHelper.kt @@ -2,19 +2,26 @@ package org.koitharu.kotatsu.reader.ui import android.content.Context import android.net.Uri +import android.webkit.MimeTypeMap import androidx.activity.result.ActivityResultLauncher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.runInterruptible import kotlinx.coroutines.suspendCancellableCoroutine +import kotlinx.coroutines.withContext import okhttp3.HttpUrl.Companion.toHttpUrl import okio.IOException +import org.koitharu.kotatsu.base.domain.MangaUtils import org.koitharu.kotatsu.local.data.PagesCache import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.parsers.util.toFileNameSafe import org.koitharu.kotatsu.reader.domain.PageLoader +import java.io.File import kotlin.coroutines.Continuation -import kotlin.coroutines.coroutineContext import kotlin.coroutines.resume +private const val MAX_FILENAME_LENGTH = 10 +private const val EXTENSION_FALLBACK = "png" + class PageSaveHelper( private val cache: PagesCache, context: Context, @@ -28,22 +35,17 @@ class PageSaveHelper( page: MangaPage, saveLauncher: ActivityResultLauncher, ): Uri { - var pageFile = cache[page.url] - var fileName = pageFile?.name - if (fileName == null) { - fileName = pageLoader.getPageUrl(page).toHttpUrl().pathSegments.last() - } - val cc = coroutineContext - val destination = suspendCancellableCoroutine { cont -> - continuation = cont - Dispatchers.Main.dispatch(cc) { - saveLauncher.launch(fileName) + val pageUrl = pageLoader.getPageUrl(page) + val pageFile = pageLoader.loadPage(page, force = false) + val proposedName = getProposedFileName(pageUrl, pageFile) + val destination = withContext(Dispatchers.Main) { + suspendCancellableCoroutine { cont -> + continuation = cont + saveLauncher.launch(proposedName) + }.also { + continuation = null } } - continuation = null - if (pageFile == null) { - pageFile = pageLoader.loadPage(page, force = false) - } runInterruptible(Dispatchers.IO) { contentResolver.openOutputStream(destination)?.use { output -> pageFile.inputStream().use { input -> @@ -57,4 +59,19 @@ class PageSaveHelper( fun onActivityResult(uri: Uri): Boolean = continuation?.apply { resume(uri) } != 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 + } } \ No newline at end of file