mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-03 23:58:55 +01:00 
			
		
		
		
	Revert attempts to read archives to cache first
Issues: - Apache implementation relies on methods unavailable on lower Android API levels - Using input stream implementation doesn't seem to read some files properly, but using ZipFile implementation still requires reading the entire thing into memory
This commit is contained in:
		@@ -1,10 +1,11 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.loader
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import com.github.junrar.Archive
 | 
			
		||||
import com.github.junrar.rarfile.FileHeader
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
 | 
			
		||||
import tachiyomi.core.util.system.ImageUtil
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.InputStream
 | 
			
		||||
import java.io.PipedInputStream
 | 
			
		||||
@@ -15,36 +16,30 @@ import java.io.PipedOutputStream
 | 
			
		||||
 */
 | 
			
		||||
internal class RarPageLoader(file: File) : PageLoader() {
 | 
			
		||||
 | 
			
		||||
    private val context: Application by injectLazy()
 | 
			
		||||
    private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also {
 | 
			
		||||
        it.deleteRecursively()
 | 
			
		||||
        it.mkdirs()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        Archive(file).use { rar ->
 | 
			
		||||
            rar.fileHeaders.asSequence()
 | 
			
		||||
                .filterNot { it.isDirectory }
 | 
			
		||||
                .forEach { header ->
 | 
			
		||||
                    val pageOutputStream = File(tmpDir, header.fileName.substringAfterLast("/"))
 | 
			
		||||
                        .also { it.createNewFile() }
 | 
			
		||||
                        .outputStream()
 | 
			
		||||
                    getStream(rar, header).use {
 | 
			
		||||
                        it.copyTo(pageOutputStream)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    private val rar = Archive(file)
 | 
			
		||||
 | 
			
		||||
    override var isLocal: Boolean = true
 | 
			
		||||
 | 
			
		||||
    override suspend fun getPages(): List<ReaderPage> {
 | 
			
		||||
        return DirectoryPageLoader(tmpDir).getPages()
 | 
			
		||||
        return rar.fileHeaders.asSequence()
 | 
			
		||||
            .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } }
 | 
			
		||||
            .sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
 | 
			
		||||
            .mapIndexed { i, header ->
 | 
			
		||||
                ReaderPage(i).apply {
 | 
			
		||||
                    stream = { getStream(rar, header) }
 | 
			
		||||
                    status = Page.State.READY
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .toList()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun loadPage(page: ReaderPage) {
 | 
			
		||||
        check(!isRecycled)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun recycle() {
 | 
			
		||||
        super.recycle()
 | 
			
		||||
        tmpDir.deleteRecursively()
 | 
			
		||||
        rar.close()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,52 +1,46 @@
 | 
			
		||||
package eu.kanade.tachiyomi.ui.reader.loader
 | 
			
		||||
 | 
			
		||||
import android.app.Application
 | 
			
		||||
import android.os.Build
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.Page
 | 
			
		||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
 | 
			
		||||
import org.apache.commons.compress.archivers.zip.ZipFile
 | 
			
		||||
import org.apache.commons.compress.utils.SeekableInMemoryByteChannel
 | 
			
		||||
import uy.kohesive.injekt.injectLazy
 | 
			
		||||
import java.io.ByteArrayOutputStream
 | 
			
		||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
 | 
			
		||||
import tachiyomi.core.util.system.ImageUtil
 | 
			
		||||
import java.io.File
 | 
			
		||||
import java.io.FileInputStream
 | 
			
		||||
import java.nio.charset.StandardCharsets
 | 
			
		||||
import java.util.zip.ZipFile
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Loader used to load a chapter from a .zip or .cbz file.
 | 
			
		||||
 */
 | 
			
		||||
internal class ZipPageLoader(file: File) : PageLoader() {
 | 
			
		||||
 | 
			
		||||
    private val context: Application by injectLazy()
 | 
			
		||||
    private val tmpDir = File(context.externalCacheDir, "reader_${file.hashCode()}").also {
 | 
			
		||||
        it.deleteRecursively()
 | 
			
		||||
        it.mkdirs()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    init {
 | 
			
		||||
        ByteArrayOutputStream().use { byteArrayOutputStream ->
 | 
			
		||||
            FileInputStream(file).use { it.copyTo(byteArrayOutputStream) }
 | 
			
		||||
 | 
			
		||||
            ZipFile(SeekableInMemoryByteChannel(byteArrayOutputStream.toByteArray())).use { zip ->
 | 
			
		||||
                zip.entries.asSequence()
 | 
			
		||||
                    .filterNot { it.isDirectory }
 | 
			
		||||
                    .forEach { entry ->
 | 
			
		||||
                        File(tmpDir, entry.name.substringAfterLast("/"))
 | 
			
		||||
                            .also { it.createNewFile() }
 | 
			
		||||
                            .outputStream().use { pageOutputStream ->
 | 
			
		||||
                                zip.getInputStream(entry).copyTo(pageOutputStream)
 | 
			
		||||
                                pageOutputStream.flush()
 | 
			
		||||
                            }
 | 
			
		||||
                    }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    private val zip = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
 | 
			
		||||
        ZipFile(file, StandardCharsets.ISO_8859_1)
 | 
			
		||||
    } else {
 | 
			
		||||
        ZipFile(file)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override var isLocal: Boolean = true
 | 
			
		||||
 | 
			
		||||
    override suspend fun getPages(): List<ReaderPage> {
 | 
			
		||||
        return DirectoryPageLoader(tmpDir).getPages()
 | 
			
		||||
        return zip.entries().asSequence()
 | 
			
		||||
            .filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
 | 
			
		||||
            .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
 | 
			
		||||
            .mapIndexed { i, entry ->
 | 
			
		||||
                ReaderPage(i).apply {
 | 
			
		||||
                    stream = { zip.getInputStream(entry) }
 | 
			
		||||
                    status = Page.State.READY
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .toList()
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override suspend fun loadPage(page: ReaderPage) {
 | 
			
		||||
        check(!isRecycled)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun recycle() {
 | 
			
		||||
        super.recycle()
 | 
			
		||||
        tmpDir.deleteRecursively()
 | 
			
		||||
        zip.close()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user