Move archive related code to :core:archive
(cherry picked from commit bd7b35419861df6d426d6ec0a188391910d0f615)
This commit is contained in:
parent
f7b9f372bd
commit
a1e0a1cd4b
26 changed files with 80 additions and 62 deletions
|
|
@ -169,11 +169,11 @@ dependencies {
|
|||
implementation(projects.i18n)
|
||||
// KMK -->
|
||||
implementation(projects.i18nKmk)
|
||||
implementation(projects.flagkit)
|
||||
// KMK <--
|
||||
// SY -->
|
||||
implementation(projects.i18nSy)
|
||||
// SY <--
|
||||
implementation(projects.core.archive)
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.coreMetadata)
|
||||
implementation(projects.sourceApi)
|
||||
|
|
@ -280,6 +280,7 @@ dependencies {
|
|||
implementation(libs.material.kolor)
|
||||
implementation(libs.haze)
|
||||
implementation(compose.colorpicker)
|
||||
implementation(projects.flagkit)
|
||||
// KMK <--
|
||||
|
||||
// Logging
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import mihon.core.archive.CbzCrypto
|
||||
import tachiyomi.core.common.preference.TriState
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfo
|
||||
import tachiyomi.core.metadata.comicinfo.ComicInfoPublishingStatus
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ import eu.kanade.presentation.more.settings.Preference
|
|||
import eu.kanade.tachiyomi.core.security.SecurityPreferences
|
||||
import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
|
||||
import eu.kanade.tachiyomi.ui.category.biometric.BiometricTimesScreen
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.authenticate
|
||||
import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import kotlinx.collections.immutable.toImmutableMap
|
||||
import mihon.core.archive.CbzCrypto
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.i18n.sy.SYMR
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@ import coil3.fetch.SourceFetchResult
|
|||
import coil3.request.Options
|
||||
import coil3.request.bitmapConfig
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto.getCoverStream
|
||||
import eu.kanade.tachiyomi.util.system.GLUtil
|
||||
import mihon.core.common.archive.archiveReader
|
||||
import mihon.core.archive.CbzCrypto
|
||||
import mihon.core.archive.CbzCrypto.getCoverStream
|
||||
import mihon.core.archive.archiveReader
|
||||
import okio.BufferedSource
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.decoder.ImageDecoder
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import eu.kanade.tachiyomi.data.notification.NotificationHandler
|
|||
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil.NOMEDIA_FILE
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
|
|
@ -44,7 +43,8 @@ import kotlinx.coroutines.flow.update
|
|||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.supervisorScope
|
||||
import logcat.LogPriority
|
||||
import mihon.core.common.archive.ZipWriter
|
||||
import mihon.core.archive.CbzCrypto
|
||||
import mihon.core.archive.ZipWriter
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import okhttp3.Response
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
|
|
|
|||
|
|
@ -26,11 +26,11 @@ import eu.kanade.tachiyomi.extension.ExtensionManager
|
|||
import eu.kanade.tachiyomi.network.JavaScriptEngine
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.source.AndroidSourceManager
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import exh.eh.EHentaiUpdateHelper
|
||||
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.protobuf.ProtoBuf
|
||||
import mihon.core.archive.CbzCrypto
|
||||
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
|
||||
import nl.adaptivity.xmlutil.XmlDeclMode
|
||||
import nl.adaptivity.xmlutil.core.XmlVersion
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import kotlinx.coroutines.async
|
|||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import mihon.core.common.archive.ArchiveReader
|
||||
import mihon.core.archive.ArchiveReader
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ import eu.kanade.tachiyomi.source.online.HttpSource
|
|||
import eu.kanade.tachiyomi.source.online.all.MergedSource
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
|
||||
import mihon.core.common.archive.archiveReader
|
||||
import mihon.core.archive.archiveReader
|
||||
import mihon.core.archive.epubReader
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
import tachiyomi.core.common.util.lang.withIOContext
|
||||
import tachiyomi.core.common.util.system.logcat
|
||||
|
|
@ -127,7 +128,7 @@ class ChapterLoader(
|
|||
when (format) {
|
||||
is Format.Directory -> DirectoryPageLoader(format.file)
|
||||
is Format.Archive -> ArchivePageLoader(format.file.archiveReader(context))
|
||||
is Format.Epub -> EpubPageLoader(format.file.archiveReader(context))
|
||||
is Format.Epub -> EpubPageLoader(format.file.epubReader(context))
|
||||
}
|
||||
}
|
||||
else -> error(context.stringResource(MR.strings.loader_not_implemented_error))
|
||||
|
|
@ -145,7 +146,7 @@ class ChapterLoader(
|
|||
when (format) {
|
||||
is Format.Directory -> DirectoryPageLoader(format.file)
|
||||
is Format.Archive -> ArchivePageLoader(format.file.archiveReader(context))
|
||||
is Format.Epub -> EpubPageLoader(format.file.archiveReader(context))
|
||||
is Format.Epub -> EpubPageLoader(format.file.epubReader(context))
|
||||
}
|
||||
}
|
||||
source is HttpSource -> HttpPageLoader(chapter, source)
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.Source
|
|||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import mihon.core.common.archive.archiveReader
|
||||
import mihon.core.archive.archiveReader
|
||||
import tachiyomi.domain.manga.model.Manga
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
|
|
|
|||
|
|
@ -2,27 +2,22 @@ package eu.kanade.tachiyomi.ui.reader.loader
|
|||
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||
import mihon.core.common.archive.ArchiveReader
|
||||
import mihon.core.archive.EpubReader
|
||||
|
||||
/**
|
||||
* Loader used to load a chapter from a .epub file.
|
||||
*/
|
||||
internal class EpubPageLoader(reader: ArchiveReader) : PageLoader() {
|
||||
|
||||
private val epub = EpubFile(reader)
|
||||
internal class EpubPageLoader(private val reader: EpubReader) : PageLoader() {
|
||||
|
||||
override var isLocal: Boolean = true
|
||||
|
||||
override suspend fun getPages(): List<ReaderPage> {
|
||||
return epub.getImagesFromPages()
|
||||
.mapIndexed { i, path ->
|
||||
val streamFn = { epub.getInputStream(path)!! }
|
||||
ReaderPage(i).apply {
|
||||
stream = streamFn
|
||||
status = Page.State.READY
|
||||
}
|
||||
return reader.getImagesFromPages().mapIndexed { i, path ->
|
||||
ReaderPage(i).apply {
|
||||
stream = { reader.getInputStream(path)!! }
|
||||
status = Page.State.READY
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadPage(page: ReaderPage) {
|
||||
|
|
@ -31,6 +26,6 @@ internal class EpubPageLoader(reader: ArchiveReader) : PageLoader() {
|
|||
|
||||
override fun recycle() {
|
||||
super.recycle()
|
||||
epub.close()
|
||||
reader.close()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
1
core/archive/.gitignore
vendored
Normal file
1
core/archive/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
/build
|
||||
19
core/archive/build.gradle.kts
Normal file
19
core/archive/build.gradle.kts
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
plugins {
|
||||
id("mihon.library")
|
||||
kotlin("android")
|
||||
kotlin("plugin.serialization")
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = "mihon.core.archive"
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(libs.jsoup)
|
||||
implementation(libs.libarchive)
|
||||
implementation(libs.unifile)
|
||||
// KMK -->
|
||||
implementation(projects.core.common)
|
||||
implementation(libs.injekt.core)
|
||||
// KMK <--
|
||||
}
|
||||
2
core/archive/src/main/AndroidManifest.xml
Normal file
2
core/archive/src/main/AndroidManifest.xml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest />
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package mihon.core.common.archive
|
||||
package mihon.core.archive
|
||||
|
||||
class ArchiveEntry(
|
||||
val name: String,
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package mihon.core.common.archive
|
||||
package mihon.core.archive
|
||||
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import me.zhanghai.android.libarchive.Archive
|
||||
import me.zhanghai.android.libarchive.ArchiveEntry
|
||||
import me.zhanghai.android.libarchive.ArchiveException
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
package mihon.core.common.archive
|
||||
package mihon.core.archive
|
||||
|
||||
import android.content.Context
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.system.Os
|
||||
import android.system.OsConstants
|
||||
import com.hippo.unifile.UniFile
|
||||
import me.zhanghai.android.libarchive.ArchiveException
|
||||
import tachiyomi.core.common.storage.openFileDescriptor
|
||||
import java.io.Closeable
|
||||
import java.io.InputStream
|
||||
|
||||
|
|
@ -90,5 +87,3 @@ class ArchiveReader(pfd: ParcelFileDescriptor) : Closeable {
|
|||
Os.munmap(address, size)
|
||||
}
|
||||
}
|
||||
|
||||
fun UniFile.archiveReader(context: Context) = openFileDescriptor(context, "r").use { ArchiveReader(it) }
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package eu.kanade.tachiyomi.util.storage
|
||||
package mihon.core.archive
|
||||
|
||||
import android.security.keystore.KeyGenParameterSpec
|
||||
import android.security.keystore.KeyProperties
|
||||
|
|
@ -9,7 +9,6 @@ import kotlinx.coroutines.flow.SharingStarted
|
|||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import mihon.core.common.archive.ArchiveReader
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.BufferedInputStream
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package eu.kanade.tachiyomi.util.storage
|
||||
package mihon.core.archive
|
||||
|
||||
import mihon.core.common.archive.ArchiveReader
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import java.io.Closeable
|
||||
|
|
@ -8,9 +7,9 @@ import java.io.File
|
|||
import java.io.InputStream
|
||||
|
||||
/**
|
||||
* Wrapper over ZipFile to load files in epub format.
|
||||
* Wrapper over ArchiveReader to load files in epub format.
|
||||
*/
|
||||
class EpubFile(private val reader: ArchiveReader) : Closeable by reader {
|
||||
class EpubReader(private val reader: ArchiveReader) : Closeable by reader {
|
||||
|
||||
/**
|
||||
* Path separator used by this epub.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
package mihon.core.archive
|
||||
|
||||
import android.content.Context
|
||||
import android.os.ParcelFileDescriptor
|
||||
import com.hippo.unifile.UniFile
|
||||
|
||||
internal fun UniFile.openFileDescriptor(context: Context, mode: String): ParcelFileDescriptor =
|
||||
context.contentResolver.openFileDescriptor(uri, mode) ?: error("Failed to open file descriptor: ${filePath ?: uri}")
|
||||
|
||||
fun UniFile.archiveReader(context: Context) = openFileDescriptor(context, "r").use { ArchiveReader(it) }
|
||||
|
||||
fun UniFile.epubReader(context: Context) = EpubReader(archiveReader(context))
|
||||
|
|
@ -1,15 +1,13 @@
|
|||
package mihon.core.common.archive
|
||||
package mihon.core.archive
|
||||
|
||||
import android.content.Context
|
||||
import android.system.Os
|
||||
import android.system.StructStat
|
||||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.util.storage.CbzCrypto
|
||||
import me.zhanghai.android.libarchive.Archive
|
||||
import me.zhanghai.android.libarchive.ArchiveEntry
|
||||
import me.zhanghai.android.libarchive.ArchiveEntry.AE_IFREG
|
||||
import me.zhanghai.android.libarchive.ArchiveException
|
||||
import tachiyomi.core.common.storage.openFileDescriptor
|
||||
import java.io.Closeable
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
|
|
@ -110,10 +108,10 @@ private fun StructStat.toArchiveStat() = ArchiveEntry.StructStat().apply {
|
|||
stSize = st_size
|
||||
stBlksize = st_blksize
|
||||
stBlocks = st_blocks
|
||||
stAtim = timespec(st_atime)
|
||||
stMtim = timespec(st_mtime)
|
||||
stCtim = timespec(st_ctime)
|
||||
stAtim = st_atime.toTimespec()
|
||||
stMtim = st_mtime.toTimespec()
|
||||
stCtim = st_ctime.toTimespec()
|
||||
stIno = st_ino
|
||||
}
|
||||
|
||||
private fun timespec(tvSec: Long) = ArchiveEntry.StructTimespec().also { it.tvSec = tvSec }
|
||||
private fun Long.toTimespec() = ArchiveEntry.StructTimespec().also { it.tvSec = this }
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
package tachiyomi.core.common.storage
|
||||
|
||||
import android.content.Context
|
||||
import android.os.ParcelFileDescriptor
|
||||
import com.hippo.unifile.UniFile
|
||||
|
||||
val UniFile.extension: String?
|
||||
|
|
@ -12,6 +10,3 @@ val UniFile.nameWithoutExtension: String?
|
|||
|
||||
val UniFile.displayablePath: String
|
||||
get() = filePath ?: uri.toString()
|
||||
|
||||
fun UniFile.openFileDescriptor(context: Context, mode: String): ParcelFileDescriptor =
|
||||
context.contentResolver.openFileDescriptor(uri, mode) ?: error("Failed to open file descriptor: $displayablePath")
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
|
|||
rootProject.name = "Komikku"
|
||||
include(":app")
|
||||
include(":core-metadata")
|
||||
include(":core:archive")
|
||||
include(":core:common")
|
||||
include(":data")
|
||||
include(":domain")
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ kotlin {
|
|||
}
|
||||
val androidMain by getting {
|
||||
dependencies {
|
||||
implementation(projects.core.archive)
|
||||
implementation(projects.core.common)
|
||||
implementation(projects.coreMetadata)
|
||||
|
||||
|
|
|
|||
|
|
@ -11,14 +11,14 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.decodeFromStream
|
||||
import logcat.LogPriority
|
||||
import mihon.core.common.archive.ZipWriter
|
||||
import mihon.core.common.archive.archiveReader
|
||||
import mihon.core.archive.ZipWriter
|
||||
import mihon.core.archive.archiveReader
|
||||
import mihon.core.archive.epubReader
|
||||
import nl.adaptivity.xmlutil.AndroidXmlReader
|
||||
import nl.adaptivity.xmlutil.serialization.XML
|
||||
import tachiyomi.core.common.i18n.stringResource
|
||||
|
|
@ -344,7 +344,7 @@ actual class LocalSource(
|
|||
|
||||
val format = Format.valueOf(chapterFile)
|
||||
if (format is Format.Epub) {
|
||||
EpubFile(format.file.archiveReader(context)).use { epub ->
|
||||
format.file.epubReader(context).use { epub ->
|
||||
epub.fillMetadata(manga, this)
|
||||
}
|
||||
}
|
||||
|
|
@ -414,7 +414,7 @@ actual class LocalSource(
|
|||
}
|
||||
}
|
||||
is Format.Epub -> {
|
||||
EpubFile(format.file.archiveReader(context)).use { epub ->
|
||||
format.file.epubReader(context).use { epub ->
|
||||
val entry = epub.getImagesFromPages().firstOrNull()
|
||||
|
||||
entry?.let { coverManager.update(manga, epub.getInputStream(it)!!) }
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import android.content.Context
|
|||
import com.hippo.unifile.UniFile
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import mihon.core.common.archive.ZipWriter
|
||||
import mihon.core.archive.ZipWriter
|
||||
import tachiyomi.core.common.storage.nameWithoutExtension
|
||||
import tachiyomi.core.common.util.system.ImageUtil
|
||||
import tachiyomi.source.local.io.LocalSourceFileSystem
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package tachiyomi.source.local.metadata
|
|||
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||
import mihon.core.archive.EpubReader
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
|
@ -10,7 +10,7 @@ import java.util.Locale
|
|||
/**
|
||||
* Fills manga and chapter metadata using this epub file's metadata.
|
||||
*/
|
||||
fun EpubFile.fillMetadata(manga: SManga, chapter: SChapter) {
|
||||
fun EpubReader.fillMetadata(manga: SManga, chapter: SChapter) {
|
||||
val ref = getPackageHref()
|
||||
val doc = getPackageDocument(ref)
|
||||
|
||||
Loading…
Reference in a new issue