From 3599a38ad6e82be6367e9be71c637cdfaf784c83 Mon Sep 17 00:00:00 2001 From: AntsyLich <59261191+antsylich@users.noreply.github.com> Date: Thu, 5 Sep 2024 12:00:46 +0200 Subject: [PATCH] Move archive related code to :core:archive Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> --- app/build.gradle.kts | 1 + .../data/download/manga/MangaDownloader.kt | 2 +- .../ui/reader/loader/ArchivePageLoader.kt | 2 +- .../ui/reader/loader/ChapterLoader.kt | 5 +++-- .../ui/reader/loader/DownloadPageLoader.kt | 2 +- .../ui/reader/loader/EpubPageLoader.kt | 21 +++++++------------ core/archive/.gitignore | 1 + core/archive/build.gradle.kts | 15 +++++++++++++ core/archive/src/main/AndroidManifest.xml | 2 ++ .../mihon/core}/archive/ArchiveEntry.kt | 2 +- .../mihon/core}/archive/ArchiveInputStream.kt | 4 ++-- .../mihon/core}/archive/ArchiveReader.kt | 18 +++++++--------- .../kotlin/mihon/core/archive}/EpubFile.kt | 7 +++---- .../mihon/core/archive/UniFileExtensions.kt | 12 +++++++++++ .../kotlin/mihon/core}/archive/ZipWriter.kt | 11 +++++----- .../core/common/storage/UniFileExtensions.kt | 5 ----- settings.gradle.kts | 1 + source-local/build.gradle.kts | 1 + .../local/entries/manga/LocalMangaSource.kt | 8 +++---- .../{EpubFile.kt => EpubReaderExtensions.kt} | 4 ++-- 20 files changed, 71 insertions(+), 53 deletions(-) create mode 100644 core/archive/.gitignore create mode 100644 core/archive/build.gradle.kts create mode 100644 core/archive/src/main/AndroidManifest.xml rename core/{common/src/main/java/mihon/core/common => archive/src/main/kotlin/mihon/core}/archive/ArchiveEntry.kt (67%) rename core/{common/src/main/java/mihon/core/common => archive/src/main/kotlin/mihon/core}/archive/ArchiveInputStream.kt (94%) rename core/{common/src/main/java/mihon/core/common => archive/src/main/kotlin/mihon/core}/archive/ArchiveReader.kt (55%) rename core/{common/src/main/java/eu/kanade/tachiyomi/util/storage => archive/src/main/kotlin/mihon/core/archive}/EpubFile.kt (95%) create mode 100644 core/archive/src/main/kotlin/mihon/core/archive/UniFileExtensions.kt rename core/{common/src/main/java/mihon/core/common => archive/src/main/kotlin/mihon/core}/archive/ZipWriter.kt (88%) rename source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/{EpubFile.kt => EpubReaderExtensions.kt} (92%) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index fb4e49f29..918208f18 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -147,6 +147,7 @@ android { dependencies { implementation(projects.i18n) + implementation(projects.core.archive) implementation(projects.core.common) implementation(projects.coreMetadata) implementation(projects.sourceApi) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/manga/MangaDownloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/manga/MangaDownloader.kt index 91fb1e2a3..110506e8b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/manga/MangaDownloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/manga/MangaDownloader.kt @@ -41,7 +41,7 @@ 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.ZipWriter import nl.adaptivity.xmlutil.serialization.XML import okhttp3.Response import okio.Throttler diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ArchivePageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ArchivePageLoader.kt index 397ac51bc..656d1c797 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ArchivePageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ArchivePageLoader.kt @@ -3,7 +3,7 @@ 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.lang.compareToCaseInsensitiveNaturalOrder -import mihon.core.common.archive.ArchiveReader +import mihon.core.archive.ArchiveReader import tachiyomi.core.common.util.system.ImageUtil /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt index 3d5732641..f954c33ad 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ChapterLoader.kt @@ -7,7 +7,8 @@ import eu.kanade.tachiyomi.source.MangaSource import eu.kanade.tachiyomi.source.online.HttpSource 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 @@ -98,7 +99,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) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DownloadPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DownloadPageLoader.kt index b5c499659..e21462f30 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DownloadPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DownloadPageLoader.kt @@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.MangaSource 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.entries.manga.model.Manga import uy.kohesive.injekt.injectLazy diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt index 8ace2fdee..cc43487a8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt @@ -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 { - 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() } } diff --git a/core/archive/.gitignore b/core/archive/.gitignore new file mode 100644 index 000000000..796b96d1c --- /dev/null +++ b/core/archive/.gitignore @@ -0,0 +1 @@ +/build diff --git a/core/archive/build.gradle.kts b/core/archive/build.gradle.kts new file mode 100644 index 000000000..ae2bda74d --- /dev/null +++ b/core/archive/build.gradle.kts @@ -0,0 +1,15 @@ +plugins { + id("mihon.library") + kotlin("android") + kotlin("plugin.serialization") +} + +android { + namespace = "mihon.core.archive" +} + +dependencies { + implementation(libs.jsoup) + implementation(libs.libarchive) + implementation(libs.unifile) +} diff --git a/core/archive/src/main/AndroidManifest.xml b/core/archive/src/main/AndroidManifest.xml new file mode 100644 index 000000000..8072ee00d --- /dev/null +++ b/core/archive/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/core/common/src/main/java/mihon/core/common/archive/ArchiveEntry.kt b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveEntry.kt similarity index 67% rename from core/common/src/main/java/mihon/core/common/archive/ArchiveEntry.kt rename to core/archive/src/main/kotlin/mihon/core/archive/ArchiveEntry.kt index 26240de00..a4959a95c 100644 --- a/core/common/src/main/java/mihon/core/common/archive/ArchiveEntry.kt +++ b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveEntry.kt @@ -1,4 +1,4 @@ -package mihon.core.common.archive +package mihon.core.archive class ArchiveEntry( val name: String, diff --git a/core/common/src/main/java/mihon/core/common/archive/ArchiveInputStream.kt b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveInputStream.kt similarity index 94% rename from core/common/src/main/java/mihon/core/common/archive/ArchiveInputStream.kt rename to core/archive/src/main/kotlin/mihon/core/archive/ArchiveInputStream.kt index 1499867c8..a14d803b1 100644 --- a/core/common/src/main/java/mihon/core/common/archive/ArchiveInputStream.kt +++ b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveInputStream.kt @@ -1,4 +1,4 @@ -package mihon.core.common.archive +package mihon.core.archive import me.zhanghai.android.libarchive.Archive import me.zhanghai.android.libarchive.ArchiveEntry @@ -7,7 +7,7 @@ import java.io.InputStream import java.nio.ByteBuffer import kotlin.concurrent.Volatile -class ArchiveInputStream(buffer: Long, size: Long) : InputStream() { +internal class ArchiveInputStream(buffer: Long, size: Long) : InputStream() { private val lock = Any() @Volatile diff --git a/core/common/src/main/java/mihon/core/common/archive/ArchiveReader.kt b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveReader.kt similarity index 55% rename from core/common/src/main/java/mihon/core/common/archive/ArchiveReader.kt rename to core/archive/src/main/kotlin/mihon/core/archive/ArchiveReader.kt index 28467d0fe..eea35f5ae 100644 --- a/core/common/src/main/java/mihon/core/common/archive/ArchiveReader.kt +++ b/core/archive/src/main/kotlin/mihon/core/archive/ArchiveReader.kt @@ -1,24 +1,22 @@ -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 class ArchiveReader(pfd: ParcelFileDescriptor) : Closeable { - val size = pfd.statSize - val address = Os.mmap(0, size, OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, pfd.fileDescriptor, 0) + private val size = pfd.statSize + private val address = Os.mmap(0, size, OsConstants.PROT_READ, OsConstants.MAP_PRIVATE, pfd.fileDescriptor, 0) - inline fun useEntries(block: (Sequence) -> T): T = - ArchiveInputStream(address, size).use { block(generateSequence { it.getNextEntry() }) } + fun useEntries(block: (Sequence) -> T): T = ArchiveInputStream(address, size).use { + block(generateSequence { it.getNextEntry() }) + } fun getInputStream(entryName: String): InputStream? { - val archive = ArchiveInputStream(address, size) + val archive = mihon.core.archive.ArchiveInputStream(address, size) try { while (true) { val entry = archive.getNextEntry() ?: break @@ -38,5 +36,3 @@ class ArchiveReader(pfd: ParcelFileDescriptor) : Closeable { Os.munmap(address, size) } } - -fun UniFile.archiveReader(context: Context) = openFileDescriptor(context, "r").use { ArchiveReader(it) } diff --git a/core/common/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt b/core/archive/src/main/kotlin/mihon/core/archive/EpubFile.kt similarity index 95% rename from core/common/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt rename to core/archive/src/main/kotlin/mihon/core/archive/EpubFile.kt index b194c5ee3..620602c81 100644 --- a/core/common/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt +++ b/core/archive/src/main/kotlin/mihon/core/archive/EpubFile.kt @@ -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. diff --git a/core/archive/src/main/kotlin/mihon/core/archive/UniFileExtensions.kt b/core/archive/src/main/kotlin/mihon/core/archive/UniFileExtensions.kt new file mode 100644 index 000000000..a87d9c304 --- /dev/null +++ b/core/archive/src/main/kotlin/mihon/core/archive/UniFileExtensions.kt @@ -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.toString()}") + +fun UniFile.archiveReader(context: Context) = openFileDescriptor(context, "r").use { ArchiveReader(it) } + +fun UniFile.epubReader(context: Context) = EpubReader(archiveReader(context)) diff --git a/core/common/src/main/java/mihon/core/common/archive/ZipWriter.kt b/core/archive/src/main/kotlin/mihon/core/archive/ZipWriter.kt similarity index 88% rename from core/common/src/main/java/mihon/core/common/archive/ZipWriter.kt rename to core/archive/src/main/kotlin/mihon/core/archive/ZipWriter.kt index b5d201516..6a7cc0de7 100644 --- a/core/common/src/main/java/mihon/core/common/archive/ZipWriter.kt +++ b/core/archive/src/main/kotlin/mihon/core/archive/ZipWriter.kt @@ -1,4 +1,4 @@ -package mihon.core.common.archive +package mihon.core.archive import android.content.Context import android.system.Os @@ -7,7 +7,6 @@ import com.hippo.unifile.UniFile import me.zhanghai.android.libarchive.Archive import me.zhanghai.android.libarchive.ArchiveEntry import me.zhanghai.android.libarchive.ArchiveException -import tachiyomi.core.common.storage.openFileDescriptor import java.io.Closeable import java.nio.ByteBuffer @@ -65,10 +64,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 } diff --git a/core/common/src/main/java/tachiyomi/core/common/storage/UniFileExtensions.kt b/core/common/src/main/java/tachiyomi/core/common/storage/UniFileExtensions.kt index 4b04ff405..8bbd9b3a7 100644 --- a/core/common/src/main/java/tachiyomi/core/common/storage/UniFileExtensions.kt +++ b/core/common/src/main/java/tachiyomi/core/common/storage/UniFileExtensions.kt @@ -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") diff --git a/settings.gradle.kts b/settings.gradle.kts index e47d86464..90f8b4de0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -40,6 +40,7 @@ enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") rootProject.name = "Aniyomi" include(":app") include(":core-metadata") +include(":core:archive") include(":core:common") include(":data") include(":domain") diff --git a/source-local/build.gradle.kts b/source-local/build.gradle.kts index 9922d3c75..06e08cd45 100644 --- a/source-local/build.gradle.kts +++ b/source-local/build.gradle.kts @@ -16,6 +16,7 @@ kotlin { } val androidMain by getting { dependencies { + implementation(projects.core.archive) implementation(projects.core.common) implementation(projects.coreMetadata) diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/entries/manga/LocalMangaSource.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/entries/manga/LocalMangaSource.kt index 92c03b943..07eb8fdd4 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/entries/manga/LocalMangaSource.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/entries/manga/LocalMangaSource.kt @@ -11,13 +11,13 @@ 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.archiveReader +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 @@ -270,7 +270,7 @@ actual class LocalMangaSource( 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) } } @@ -359,7 +359,7 @@ actual class LocalMangaSource( } } 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)!!) } diff --git a/source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubFile.kt b/source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubReaderExtensions.kt similarity index 92% rename from source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubFile.kt rename to source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubReaderExtensions.kt index 6bade530b..388156bc7 100644 --- a/source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubFile.kt +++ b/source-local/src/androidMain/kotlin/tachiyomi/source/local/metadata/EpubReaderExtensions.kt @@ -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)