mirror of
https://github.com/mihonapp/mihon.git
synced 2025-04-20 19:28:45 +02:00
Merge remote branch abdallahmehiz/tachiyomi:7zip
This commit is contained in:
commit
c1466ada2b
@ -210,6 +210,7 @@ dependencies {
|
|||||||
implementation(libs.disklrucache)
|
implementation(libs.disklrucache)
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.junrar)
|
implementation(libs.junrar)
|
||||||
|
implementation(libs.bundles.sevenzip)
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
implementation(libs.preferencektx)
|
implementation(libs.preferencektx)
|
||||||
|
@ -98,6 +98,7 @@ class ChapterLoader(
|
|||||||
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(tempFileManager.createTempFile(format.file))
|
||||||
|
is Format.SevenZip -> SevenZipPageLoader(format.file.toTempFile(context))
|
||||||
is Format.Rar -> try {
|
is Format.Rar -> try {
|
||||||
RarPageLoader(tempFileManager.createTempFile(format.file))
|
RarPageLoader(tempFileManager.createTempFile(format.file))
|
||||||
} catch (e: UnsupportedRarV5Exception) {
|
} catch (e: UnsupportedRarV5Exception) {
|
||||||
|
@ -0,0 +1,36 @@
|
|||||||
|
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.SevenZUtil.getImages
|
||||||
|
import org.apache.commons.compress.archivers.sevenz.SevenZFile
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loader used to load a chapter from a .7z or .cb7 file.
|
||||||
|
*/
|
||||||
|
internal class SevenZipPageLoader(file: File) : PageLoader() {
|
||||||
|
|
||||||
|
private val zip by lazy { SevenZFile(file) }
|
||||||
|
|
||||||
|
override var isLocal: Boolean = true
|
||||||
|
|
||||||
|
override suspend fun getPages(): List<ReaderPage> {
|
||||||
|
return zip.getImages()
|
||||||
|
.mapIndexed { i, entry ->
|
||||||
|
ReaderPage(i).apply {
|
||||||
|
stream = { entry.copyOf().inputStream() }
|
||||||
|
status = Page.State.READY
|
||||||
|
}
|
||||||
|
}.toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun loadPage(page: ReaderPage) {
|
||||||
|
check(!isRecycled)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun recycle() {
|
||||||
|
super.recycle()
|
||||||
|
zip.close()
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,7 @@ dependencies {
|
|||||||
implementation(libs.image.decoder)
|
implementation(libs.image.decoder)
|
||||||
|
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
|
implementation(libs.bundles.sevenzip)
|
||||||
|
|
||||||
api(kotlinx.coroutines.core)
|
api(kotlinx.coroutines.core)
|
||||||
api(kotlinx.serialization.json)
|
api(kotlinx.serialization.json)
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package eu.kanade.tachiyomi.util.storage
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
|
import org.apache.commons.compress.archivers.sevenz.SevenZFile
|
||||||
|
import tachiyomi.core.util.system.ImageUtil
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
object SevenZUtil {
|
||||||
|
fun SevenZFile.getImages(): Sequence<ByteArray> {
|
||||||
|
return generateSequence { runCatching { getNextEntry() }.getOrNull() }
|
||||||
|
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { getInputStream(it) } }
|
||||||
|
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
|
||||||
|
.map(::getInputStream)
|
||||||
|
.map { it.use(InputStream::readBytes) } // ByteArray
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,8 @@ 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"
|
||||||
junrar = "com.github.junrar:junrar:7.5.5"
|
junrar = "com.github.junrar:junrar:7.5.5"
|
||||||
|
common-compress = "org.apache.commons:commons-compress:1.25.0"
|
||||||
|
xz = "org.tukaani:xz:1.9"
|
||||||
|
|
||||||
sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }
|
sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }
|
||||||
sqlite-ktx = { module = "androidx.sqlite:sqlite-ktx", version.ref = "sqlite" }
|
sqlite-ktx = { module = "androidx.sqlite:sqlite-ktx", version.ref = "sqlite" }
|
||||||
@ -105,3 +107,4 @@ sqldelight = ["sqldelight-android-driver", "sqldelight-coroutines", "sqldelight-
|
|||||||
voyager = ["voyager-navigator", "voyager-screenmodel", "voyager-tab-navigator", "voyager-transitions"]
|
voyager = ["voyager-navigator", "voyager-screenmodel", "voyager-tab-navigator", "voyager-transitions"]
|
||||||
richtext = ["richtext-commonmark", "richtext-m3"]
|
richtext = ["richtext-commonmark", "richtext-m3"]
|
||||||
test = ["junit", "kotest-assertions", "mockk"]
|
test = ["junit", "kotest-assertions", "mockk"]
|
||||||
|
sevenzip = ["common-compress", "xz"]
|
@ -13,6 +13,7 @@ kotlin {
|
|||||||
|
|
||||||
implementation(libs.unifile)
|
implementation(libs.unifile)
|
||||||
implementation(libs.junrar)
|
implementation(libs.junrar)
|
||||||
|
implementation(libs.bundles.sevenzip)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val androidMain by getting {
|
val androidMain by getting {
|
||||||
|
@ -11,6 +11,7 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
|
||||||
import eu.kanade.tachiyomi.util.storage.EpubFile
|
import eu.kanade.tachiyomi.util.storage.EpubFile
|
||||||
|
import eu.kanade.tachiyomi.util.storage.SevenZUtil.getImages
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
@ -18,6 +19,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.sevenz.SevenZFile
|
||||||
import tachiyomi.core.i18n.stringResource
|
import tachiyomi.core.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
|
||||||
@ -340,6 +342,13 @@ actual class LocalSource(
|
|||||||
entry?.let { coverManager.update(manga, zip.getInputStream(it)) }
|
entry?.let { coverManager.update(manga, zip.getInputStream(it)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
is Format.SevenZip -> {
|
||||||
|
SevenZFile(format.file.toTempFile(context)).use { archive ->
|
||||||
|
val entry = archive.getImages().firstOrNull()
|
||||||
|
|
||||||
|
entry?.let { coverManager.update(manga, it.inputStream()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
is Format.Rar -> {
|
is Format.Rar -> {
|
||||||
JunrarArchive(tempFileManager.createTempFile(format.file)).use { archive ->
|
JunrarArchive(tempFileManager.createTempFile(format.file)).use { archive ->
|
||||||
val entry = archive.fileHeaders
|
val entry = archive.fileHeaders
|
||||||
|
@ -5,7 +5,7 @@ import tachiyomi.core.storage.extension
|
|||||||
|
|
||||||
object Archive {
|
object Archive {
|
||||||
|
|
||||||
private val SUPPORTED_ARCHIVE_TYPES = listOf("zip", "cbz", "rar", "cbr", "epub")
|
private val SUPPORTED_ARCHIVE_TYPES = listOf("zip", "cbz", "7z", "cb7", "rar", "cbr", "epub")
|
||||||
|
|
||||||
fun isSupported(file: UniFile): Boolean {
|
fun isSupported(file: UniFile): Boolean {
|
||||||
return file.extension in SUPPORTED_ARCHIVE_TYPES
|
return file.extension in SUPPORTED_ARCHIVE_TYPES
|
||||||
|
@ -6,6 +6,7 @@ import tachiyomi.core.storage.extension
|
|||||||
sealed interface Format {
|
sealed interface Format {
|
||||||
data class Directory(val file: UniFile) : Format
|
data class Directory(val file: UniFile) : Format
|
||||||
data class Zip(val file: UniFile) : Format
|
data class Zip(val file: UniFile) : Format
|
||||||
|
data class SevenZip(val file: UniFile) : Format
|
||||||
data class Rar(val file: UniFile) : Format
|
data class Rar(val file: UniFile) : Format
|
||||||
data class Epub(val file: UniFile) : Format
|
data class Epub(val file: UniFile) : Format
|
||||||
|
|
||||||
@ -17,6 +18,7 @@ sealed interface Format {
|
|||||||
when {
|
when {
|
||||||
isDirectory -> Directory(this)
|
isDirectory -> Directory(this)
|
||||||
extension.equals("zip", true) || extension.equals("cbz", true) -> Zip(this)
|
extension.equals("zip", true) || extension.equals("cbz", true) -> Zip(this)
|
||||||
|
extension.equals("7z", true) || extension.equals("cb7", true) -> SevenZip(this)
|
||||||
extension.equals("rar", true) || extension.equals("cbr", true) -> Rar(this)
|
extension.equals("rar", true) || extension.equals("cbr", true) -> Rar(this)
|
||||||
extension.equals("epub", true) -> Epub(this)
|
extension.equals("epub", true) -> Epub(this)
|
||||||
else -> throw UnknownFormatException()
|
else -> throw UnknownFormatException()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user