mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-25 14:19:27 +03:00
Don't copy archives to temp files when opening
Co-authored-by: FooIbar <118464521+FooIbar@users.noreply.github.com>
This commit is contained in:
parent
60c5636da2
commit
0424b60b3e
15 changed files with 49 additions and 47 deletions
|
@ -219,7 +219,7 @@ dependencies {
|
||||||
// Disk
|
// Disk
|
||||||
implementation(libs.disklrucache)
|
implementation(libs.disklrucache)
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.junrar)
|
implementation(libs.bundles.archive)
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation(libs.preferencektx)
|
implementation(libs.preferencektx)
|
||||||
|
|
3
app/proguard-rules.pro
vendored
3
app/proguard-rules.pro
vendored
|
@ -76,3 +76,6 @@
|
||||||
|
|
||||||
# XmlUtil
|
# XmlUtil
|
||||||
-keep public enum nl.adaptivity.xmlutil.EventType { *; }
|
-keep public enum nl.adaptivity.xmlutil.EventType { *; }
|
||||||
|
|
||||||
|
# Apache Commons Compress
|
||||||
|
-keep class * extends org.apache.commons.compress.archivers.zip.ZipExtraField { <init>(); }
|
|
@ -38,7 +38,6 @@ import nl.adaptivity.xmlutil.XmlDeclMode
|
||||||
import nl.adaptivity.xmlutil.core.XmlVersion
|
import nl.adaptivity.xmlutil.core.XmlVersion
|
||||||
import nl.adaptivity.xmlutil.serialization.XML
|
import nl.adaptivity.xmlutil.serialization.XML
|
||||||
import tachiyomi.core.common.storage.AndroidStorageFolderProvider
|
import tachiyomi.core.common.storage.AndroidStorageFolderProvider
|
||||||
import tachiyomi.core.common.storage.UniFileTempFileManager
|
|
||||||
import tachiyomi.data.AnimeUpdateStrategyColumnAdapter
|
import tachiyomi.data.AnimeUpdateStrategyColumnAdapter
|
||||||
import tachiyomi.data.Database
|
import tachiyomi.data.Database
|
||||||
import tachiyomi.data.DateColumnAdapter
|
import tachiyomi.data.DateColumnAdapter
|
||||||
|
@ -178,8 +177,6 @@ class AppModule(val app: Application) : InjektModule {
|
||||||
ProtoBuf
|
ProtoBuf
|
||||||
}
|
}
|
||||||
|
|
||||||
addSingletonFactory { UniFileTempFileManager(app) }
|
|
||||||
|
|
||||||
addSingletonFactory { ChapterCache(app, get()) }
|
addSingletonFactory { ChapterCache(app, get()) }
|
||||||
|
|
||||||
addSingletonFactory { MangaCoverCache(app) }
|
addSingletonFactory { MangaCoverCache(app) }
|
||||||
|
|
|
@ -55,7 +55,6 @@ import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.common.preference.toggle
|
import tachiyomi.core.common.preference.toggle
|
||||||
import tachiyomi.core.common.storage.UniFileTempFileManager
|
|
||||||
import tachiyomi.core.common.util.lang.launchIO
|
import tachiyomi.core.common.util.lang.launchIO
|
||||||
import tachiyomi.core.common.util.lang.launchNonCancellable
|
import tachiyomi.core.common.util.lang.launchNonCancellable
|
||||||
import tachiyomi.core.common.util.lang.withIOContext
|
import tachiyomi.core.common.util.lang.withIOContext
|
||||||
|
@ -86,7 +85,6 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
private val sourceManager: MangaSourceManager = Injekt.get(),
|
private val sourceManager: MangaSourceManager = Injekt.get(),
|
||||||
private val downloadManager: MangaDownloadManager = Injekt.get(),
|
private val downloadManager: MangaDownloadManager = Injekt.get(),
|
||||||
private val downloadProvider: MangaDownloadProvider = Injekt.get(),
|
private val downloadProvider: MangaDownloadProvider = Injekt.get(),
|
||||||
private val tempFileManager: UniFileTempFileManager = Injekt.get(),
|
|
||||||
private val imageSaver: ImageSaver = Injekt.get(),
|
private val imageSaver: ImageSaver = Injekt.get(),
|
||||||
preferences: BasePreferences = Injekt.get(),
|
preferences: BasePreferences = Injekt.get(),
|
||||||
val readerPreferences: ReaderPreferences = Injekt.get(),
|
val readerPreferences: ReaderPreferences = Injekt.get(),
|
||||||
|
@ -277,7 +275,7 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
|
|
||||||
val context = Injekt.get<Application>()
|
val context = Injekt.get<Application>()
|
||||||
val source = sourceManager.getOrStub(manga.source)
|
val source = sourceManager.getOrStub(manga.source)
|
||||||
loader = ChapterLoader(context, downloadManager, downloadProvider, tempFileManager, manga, source)
|
loader = ChapterLoader(context, downloadManager, downloadProvider, manga, source)
|
||||||
|
|
||||||
loadChapter(loader!!, chapterList.first { chapterId == it.chapter.id })
|
loadChapter(loader!!, chapterList.first { chapterId == it.chapter.id })
|
||||||
Result.success(true)
|
Result.success(true)
|
||||||
|
@ -920,7 +918,6 @@ class ReaderViewModel @JvmOverloads constructor(
|
||||||
private fun deletePendingChapters() {
|
private fun deletePendingChapters() {
|
||||||
viewModelScope.launchNonCancellable {
|
viewModelScope.launchNonCancellable {
|
||||||
downloadManager.deletePendingChapters()
|
downloadManager.deletePendingChapters()
|
||||||
tempFileManager.deleteTempFiles()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||||
import tachiyomi.core.common.i18n.stringResource
|
import tachiyomi.core.common.i18n.stringResource
|
||||||
import tachiyomi.core.common.storage.UniFileTempFileManager
|
import tachiyomi.core.common.storage.openReadOnlyChannel
|
||||||
import tachiyomi.core.common.util.lang.withIOContext
|
import tachiyomi.core.common.util.lang.withIOContext
|
||||||
import tachiyomi.core.common.util.system.logcat
|
import tachiyomi.core.common.util.system.logcat
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
|
@ -26,7 +26,6 @@ class ChapterLoader(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val downloadManager: MangaDownloadManager,
|
private val downloadManager: MangaDownloadManager,
|
||||||
private val downloadProvider: MangaDownloadProvider,
|
private val downloadProvider: MangaDownloadProvider,
|
||||||
private val tempFileManager: UniFileTempFileManager,
|
|
||||||
private val manga: Manga,
|
private val manga: Manga,
|
||||||
private val source: MangaSource,
|
private val source: MangaSource,
|
||||||
) {
|
) {
|
||||||
|
@ -95,18 +94,17 @@ class ChapterLoader(
|
||||||
source,
|
source,
|
||||||
downloadManager,
|
downloadManager,
|
||||||
downloadProvider,
|
downloadProvider,
|
||||||
tempFileManager,
|
|
||||||
)
|
)
|
||||||
source is LocalMangaSource -> source.getFormat(chapter.chapter).let { format ->
|
source is LocalMangaSource -> source.getFormat(chapter.chapter).let { format ->
|
||||||
when (format) {
|
when (format) {
|
||||||
is Format.Directory -> DirectoryPageLoader(format.file)
|
is Format.Directory -> DirectoryPageLoader(format.file)
|
||||||
is Format.Zip -> ZipPageLoader(tempFileManager.createTempFile(format.file))
|
is Format.Zip -> ZipPageLoader(format.file.openReadOnlyChannel(context))
|
||||||
is Format.Rar -> try {
|
is Format.Rar -> try {
|
||||||
RarPageLoader(tempFileManager.createTempFile(format.file))
|
RarPageLoader(format.file.openInputStream())
|
||||||
} catch (e: UnsupportedRarV5Exception) {
|
} catch (e: UnsupportedRarV5Exception) {
|
||||||
error(context.stringResource(MR.strings.loader_rar5_error))
|
error(context.stringResource(MR.strings.loader_rar5_error))
|
||||||
}
|
}
|
||||||
is Format.Epub -> EpubPageLoader(tempFileManager.createTempFile(format.file))
|
is Format.Epub -> EpubPageLoader(format.file.openReadOnlyChannel(context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
source is HttpSource -> HttpPageLoader(chapter, source)
|
source is HttpSource -> HttpPageLoader(chapter, source)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.MangaSource
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import tachiyomi.core.common.storage.UniFileTempFileManager
|
import tachiyomi.core.common.storage.openReadOnlyChannel
|
||||||
import tachiyomi.domain.entries.manga.model.Manga
|
import tachiyomi.domain.entries.manga.model.Manga
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
@ -23,7 +23,6 @@ internal class DownloadPageLoader(
|
||||||
private val source: MangaSource,
|
private val source: MangaSource,
|
||||||
private val downloadManager: MangaDownloadManager,
|
private val downloadManager: MangaDownloadManager,
|
||||||
private val downloadProvider: MangaDownloadProvider,
|
private val downloadProvider: MangaDownloadProvider,
|
||||||
private val tempFileManager: UniFileTempFileManager,
|
|
||||||
) : PageLoader() {
|
) : PageLoader() {
|
||||||
|
|
||||||
private val context: Application by injectLazy()
|
private val context: Application by injectLazy()
|
||||||
|
@ -53,7 +52,7 @@ internal class DownloadPageLoader(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun getPagesFromArchive(file: UniFile): List<ReaderPage> {
|
private suspend fun getPagesFromArchive(file: UniFile): List<ReaderPage> {
|
||||||
val loader = ZipPageLoader(tempFileManager.createTempFile(file)).also { zipPageLoader = it }
|
val loader = ZipPageLoader(file.openReadOnlyChannel(context)).also { zipPageLoader = it }
|
||||||
return loader.getPages()
|
return loader.getPages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,14 +3,14 @@ package eu.kanade.tachiyomi.ui.reader.loader
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||||
import java.io.File
|
import java.nio.channels.SeekableByteChannel
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loader used to load a chapter from a .epub file.
|
* Loader used to load a chapter from a .epub file.
|
||||||
*/
|
*/
|
||||||
internal class EpubPageLoader(file: File) : PageLoader() {
|
internal class EpubPageLoader(channel: SeekableByteChannel) : PageLoader() {
|
||||||
|
|
||||||
private val epub = EpubFile(file)
|
private val epub = EpubFile(channel)
|
||||||
|
|
||||||
override var isLocal: Boolean = true
|
override var isLocal: Boolean = true
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
import tachiyomi.core.common.util.system.ImageUtil
|
import tachiyomi.core.common.util.system.ImageUtil
|
||||||
import java.io.File
|
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.io.PipedInputStream
|
import java.io.PipedInputStream
|
||||||
import java.io.PipedOutputStream
|
import java.io.PipedOutputStream
|
||||||
|
@ -15,9 +14,9 @@ import java.util.concurrent.Executors
|
||||||
/**
|
/**
|
||||||
* Loader used to load a chapter from a .rar or .cbr file.
|
* Loader used to load a chapter from a .rar or .cbr file.
|
||||||
*/
|
*/
|
||||||
internal class RarPageLoader(file: File) : PageLoader() {
|
internal class RarPageLoader(inputStream: InputStream) : PageLoader() {
|
||||||
|
|
||||||
private val rar = Archive(file)
|
private val rar = Archive(inputStream)
|
||||||
|
|
||||||
override var isLocal: Boolean = true
|
override var isLocal: Boolean = true
|
||||||
|
|
||||||
|
|
|
@ -3,22 +3,21 @@ package eu.kanade.tachiyomi.ui.reader.loader
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipFile
|
||||||
import tachiyomi.core.common.util.system.ImageUtil
|
import tachiyomi.core.common.util.system.ImageUtil
|
||||||
import java.io.File
|
import java.nio.channels.SeekableByteChannel
|
||||||
import java.nio.charset.StandardCharsets
|
|
||||||
import java.util.zip.ZipFile
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loader used to load a chapter from a .zip or .cbz file.
|
* Loader used to load a chapter from a .zip or .cbz file.
|
||||||
*/
|
*/
|
||||||
internal class ZipPageLoader(file: File) : PageLoader() {
|
internal class ZipPageLoader(channel: SeekableByteChannel) : PageLoader() {
|
||||||
|
|
||||||
private val zip = ZipFile(file, StandardCharsets.ISO_8859_1)
|
private val zip = ZipFile(channel)
|
||||||
|
|
||||||
override var isLocal: Boolean = true
|
override var isLocal: Boolean = true
|
||||||
|
|
||||||
override suspend fun getPages(): List<ReaderPage> {
|
override suspend fun getPages(): List<ReaderPage> {
|
||||||
return zip.entries().asSequence()
|
return zip.entries.asSequence()
|
||||||
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
|
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
|
||||||
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||||
.mapIndexed { i, entry ->
|
.mapIndexed { i, entry ->
|
||||||
|
|
|
@ -32,6 +32,7 @@ dependencies {
|
||||||
implementation(libs.image.decoder)
|
implementation(libs.image.decoder)
|
||||||
|
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
|
implementation(libs.bundles.archive)
|
||||||
|
|
||||||
api(kotlinx.coroutines.core)
|
api(kotlinx.coroutines.core)
|
||||||
api(kotlinx.serialization.json)
|
api(kotlinx.serialization.json)
|
||||||
|
|
|
@ -1,22 +1,23 @@
|
||||||
package eu.kanade.tachiyomi.util.storage
|
package eu.kanade.tachiyomi.util.storage
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipFile
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.zip.ZipEntry
|
import java.nio.channels.SeekableByteChannel
|
||||||
import java.util.zip.ZipFile
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper over ZipFile to load files in epub format.
|
* Wrapper over ZipFile to load files in epub format.
|
||||||
*/
|
*/
|
||||||
class EpubFile(file: File) : Closeable {
|
class EpubFile(channel: SeekableByteChannel) : Closeable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Zip file of this epub.
|
* Zip file of this epub.
|
||||||
*/
|
*/
|
||||||
private val zip = ZipFile(file)
|
private val zip = ZipFile(channel)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path separator used by this epub.
|
* Path separator used by this epub.
|
||||||
|
@ -33,14 +34,14 @@ class EpubFile(file: File) : Closeable {
|
||||||
/**
|
/**
|
||||||
* Returns an input stream for reading the contents of the specified zip file entry.
|
* Returns an input stream for reading the contents of the specified zip file entry.
|
||||||
*/
|
*/
|
||||||
fun getInputStream(entry: ZipEntry): InputStream {
|
fun getInputStream(entry: ZipArchiveEntry): InputStream {
|
||||||
return zip.getInputStream(entry)
|
return zip.getInputStream(entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the zip file entry for the specified name, or null if not found.
|
* Returns the zip file entry for the specified name, or null if not found.
|
||||||
*/
|
*/
|
||||||
fun getEntry(name: String): ZipEntry? {
|
fun getEntry(name: String): ZipArchiveEntry? {
|
||||||
return zip.getEntry(name)
|
return zip.getEntry(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package tachiyomi.core.common.storage
|
package tachiyomi.core.common.storage
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.os.ParcelFileDescriptor
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
|
import java.nio.channels.FileChannel
|
||||||
|
|
||||||
val UniFile.extension: String?
|
val UniFile.extension: String?
|
||||||
get() = name?.substringAfterLast('.')
|
get() = name?.substringAfterLast('.')
|
||||||
|
@ -10,3 +13,7 @@ val UniFile.nameWithoutExtension: String?
|
||||||
|
|
||||||
val UniFile.displayablePath: String
|
val UniFile.displayablePath: String
|
||||||
get() = filePath ?: uri.toString()
|
get() = filePath ?: uri.toString()
|
||||||
|
|
||||||
|
fun UniFile.openReadOnlyChannel(context: Context): FileChannel {
|
||||||
|
return ParcelFileDescriptor.AutoCloseInputStream(context.contentResolver.openFileDescriptor(uri, "r")).channel
|
||||||
|
}
|
||||||
|
|
|
@ -32,6 +32,7 @@ jsoup = "org.jsoup:jsoup:1.17.2"
|
||||||
|
|
||||||
disklrucache = "com.jakewharton:disklrucache:2.0.2"
|
disklrucache = "com.jakewharton:disklrucache:2.0.2"
|
||||||
unifile = "com.github.tachiyomiorg:unifile:7c257e1c64"
|
unifile = "com.github.tachiyomiorg:unifile:7c257e1c64"
|
||||||
|
common-compress = "org.apache.commons:commons-compress:1.25.0"
|
||||||
junrar = "com.github.junrar:junrar:7.5.5"
|
junrar = "com.github.junrar:junrar:7.5.5"
|
||||||
|
|
||||||
sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }
|
sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }
|
||||||
|
@ -110,6 +111,7 @@ seeker = "io.github.2307vivek:seeker:1.1.1"
|
||||||
truetypeparser = "io.github.yubyf:truetypeparser-light:2.1.4"
|
truetypeparser = "io.github.yubyf:truetypeparser-light:2.1.4"
|
||||||
|
|
||||||
[bundles]
|
[bundles]
|
||||||
|
archive = ["common-compress", "junrar"]
|
||||||
acra = ["acra-http", "acra-scheduler"]
|
acra = ["acra-http", "acra-scheduler"]
|
||||||
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]
|
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]
|
||||||
js-engine = ["quickjs-android"]
|
js-engine = ["quickjs-android"]
|
||||||
|
|
|
@ -12,7 +12,7 @@ kotlin {
|
||||||
api(projects.i18n)
|
api(projects.i18n)
|
||||||
|
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.junrar)
|
implementation(libs.bundles.archive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import kotlinx.serialization.json.decodeFromStream
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import nl.adaptivity.xmlutil.AndroidXmlReader
|
import nl.adaptivity.xmlutil.AndroidXmlReader
|
||||||
import nl.adaptivity.xmlutil.serialization.XML
|
import nl.adaptivity.xmlutil.serialization.XML
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipFile
|
||||||
import tachiyomi.core.common.i18n.stringResource
|
import tachiyomi.core.common.i18n.stringResource
|
||||||
import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE
|
import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE
|
||||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||||
|
@ -25,9 +26,9 @@ import tachiyomi.core.metadata.comicinfo.copyFromComicInfo
|
||||||
import tachiyomi.core.metadata.comicinfo.getComicInfo
|
import tachiyomi.core.metadata.comicinfo.getComicInfo
|
||||||
import tachiyomi.core.metadata.tachiyomi.ChapterDetails
|
import tachiyomi.core.metadata.tachiyomi.ChapterDetails
|
||||||
import tachiyomi.core.metadata.tachiyomi.MangaDetails
|
import tachiyomi.core.metadata.tachiyomi.MangaDetails
|
||||||
import tachiyomi.core.common.storage.UniFileTempFileManager
|
|
||||||
import tachiyomi.core.common.storage.extension
|
import tachiyomi.core.common.storage.extension
|
||||||
import tachiyomi.core.common.storage.nameWithoutExtension
|
import tachiyomi.core.common.storage.nameWithoutExtension
|
||||||
|
import tachiyomi.core.common.storage.openReadOnlyChannel
|
||||||
import tachiyomi.core.common.util.lang.withIOContext
|
import tachiyomi.core.common.util.lang.withIOContext
|
||||||
import tachiyomi.core.common.util.system.ImageUtil
|
import tachiyomi.core.common.util.system.ImageUtil
|
||||||
import tachiyomi.core.common.util.system.logcat
|
import tachiyomi.core.common.util.system.logcat
|
||||||
|
@ -47,7 +48,6 @@ import java.nio.charset.StandardCharsets
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.zip.ZipFile
|
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import com.github.junrar.Archive as JunrarArchive
|
import com.github.junrar.Archive as JunrarArchive
|
||||||
|
|
||||||
|
@ -59,7 +59,6 @@ actual class LocalMangaSource(
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
private val xml: XML by injectLazy()
|
private val xml: XML by injectLazy()
|
||||||
private val tempFileManager: UniFileTempFileManager by injectLazy()
|
|
||||||
|
|
||||||
private val POPULAR_FILTERS = FilterList(MangaOrderBy.Popular(context))
|
private val POPULAR_FILTERS = FilterList(MangaOrderBy.Popular(context))
|
||||||
private val LATEST_FILTERS = FilterList(MangaOrderBy.Latest(context))
|
private val LATEST_FILTERS = FilterList(MangaOrderBy.Latest(context))
|
||||||
|
@ -220,7 +219,7 @@ actual class LocalMangaSource(
|
||||||
for (chapter in chapterArchives) {
|
for (chapter in chapterArchives) {
|
||||||
when (Format.valueOf(chapter)) {
|
when (Format.valueOf(chapter)) {
|
||||||
is Format.Zip -> {
|
is Format.Zip -> {
|
||||||
ZipFile(tempFileManager.createTempFile(chapter)).use { zip: ZipFile ->
|
ZipFile(chapter.openReadOnlyChannel(context)).use { zip: ZipFile ->
|
||||||
zip.getEntry(COMIC_INFO_FILE)?.let { comicInfoFile ->
|
zip.getEntry(COMIC_INFO_FILE)?.let { comicInfoFile ->
|
||||||
zip.getInputStream(comicInfoFile).buffered().use { stream ->
|
zip.getInputStream(comicInfoFile).buffered().use { stream ->
|
||||||
return copyComicInfoFile(stream, folderPath)
|
return copyComicInfoFile(stream, folderPath)
|
||||||
|
@ -229,7 +228,7 @@ actual class LocalMangaSource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Format.Rar -> {
|
is Format.Rar -> {
|
||||||
JunrarArchive(tempFileManager.createTempFile(chapter)).use { rar ->
|
JunrarArchive(chapter.openInputStream()).use { rar ->
|
||||||
rar.fileHeaders.firstOrNull { it.fileName == COMIC_INFO_FILE }?.let { comicInfoFile ->
|
rar.fileHeaders.firstOrNull { it.fileName == COMIC_INFO_FILE }?.let { comicInfoFile ->
|
||||||
rar.getInputStream(comicInfoFile).buffered().use { stream ->
|
rar.getInputStream(comicInfoFile).buffered().use { stream ->
|
||||||
return copyComicInfoFile(stream, folderPath)
|
return copyComicInfoFile(stream, folderPath)
|
||||||
|
@ -290,7 +289,7 @@ actual class LocalMangaSource(
|
||||||
|
|
||||||
val format = Format.valueOf(chapterFile)
|
val format = Format.valueOf(chapterFile)
|
||||||
if (format is Format.Epub) {
|
if (format is Format.Epub) {
|
||||||
EpubFile(tempFileManager.createTempFile(format.file)).use { epub ->
|
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
|
||||||
epub.fillMetadata(manga, this)
|
epub.fillMetadata(manga, this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -368,8 +367,8 @@ actual class LocalMangaSource(
|
||||||
entry?.let { coverManager.update(manga, it.openInputStream()) }
|
entry?.let { coverManager.update(manga, it.openInputStream()) }
|
||||||
}
|
}
|
||||||
is Format.Zip -> {
|
is Format.Zip -> {
|
||||||
ZipFile(tempFileManager.createTempFile(format.file)).use { zip ->
|
ZipFile(format.file.openReadOnlyChannel(context)).use { zip ->
|
||||||
val entry = zip.entries().toList()
|
val entry = zip.entries.toList()
|
||||||
.sortedWith { f1, f2 ->
|
.sortedWith { f1, f2 ->
|
||||||
f1.name.compareToCaseInsensitiveNaturalOrder(
|
f1.name.compareToCaseInsensitiveNaturalOrder(
|
||||||
f2.name,
|
f2.name,
|
||||||
|
@ -387,7 +386,7 @@ actual class LocalMangaSource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Format.Rar -> {
|
is Format.Rar -> {
|
||||||
JunrarArchive(tempFileManager.createTempFile(format.file)).use { archive ->
|
JunrarArchive(format.file.openInputStream()).use { archive ->
|
||||||
val entry = archive.fileHeaders
|
val entry = archive.fileHeaders
|
||||||
.sortedWith { f1, f2 ->
|
.sortedWith { f1, f2 ->
|
||||||
f1.fileName.compareToCaseInsensitiveNaturalOrder(
|
f1.fileName.compareToCaseInsensitiveNaturalOrder(
|
||||||
|
@ -406,7 +405,7 @@ actual class LocalMangaSource(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Format.Epub -> {
|
is Format.Epub -> {
|
||||||
EpubFile(tempFileManager.createTempFile(format.file)).use { epub ->
|
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
|
||||||
val entry = epub.getImagesFromPages()
|
val entry = epub.getImagesFromPages()
|
||||||
.firstOrNull()
|
.firstOrNull()
|
||||||
?.let { epub.getEntry(it) }
|
?.let { epub.getEntry(it) }
|
||||||
|
|
Loading…
Reference in a new issue