Compare commits

...

6 Commits

Author SHA1 Message Date
6a09aca491 chore: fix some of detekt error. 2024-02-05 14:08:46 +11:00
e454e270f7 Merge branch 'main' of https://github.com/mihonapp/mihon into feat/add-cross-device-sync 2024-02-05 11:55:35 +11:00
9bff20cb1a Update dependency gradle to v8.6 (#341)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-04 13:31:52 +06:00
2ccff8cdde Fix extracting ComicInfo.xml files in local source (#325) 2024-02-04 13:27:46 +06:00
0da7ad6f1a Don't copy archives to temp files when opening (#326) 2024-02-03 23:33:18 +06:00
170daf9fb2 Update workflow dependencies (#310)
* feat: updated build_pull_request actions version

* feat: updated build_push actions version

* feat: updated issue_moderator action version

* feat: updated deprecated arguments in build_pull_request

* feat: updated deprecated arguments in build_push

* feat: removed explicit declaration of gradle version
2024-02-02 02:20:28 +06:00
25 changed files with 86 additions and 130 deletions

View File

@ -23,10 +23,10 @@ jobs:
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
uses: gradle/wrapper-validation-action@v2
- name: Dependency Review
uses: actions/dependency-review-action@v3
uses: actions/dependency-review-action@v4
- name: Set up JDK
uses: actions/setup-java@v4
@ -34,7 +34,8 @@ jobs:
java-version: 17
distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
- name: Build app and run unit tests
uses: gradle/gradle-command-action@v2
with:
arguments: detekt assembleStandardRelease testReleaseUnitTest
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest

View File

@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v4
- name: Validate Gradle Wrapper
uses: gradle/wrapper-validation-action@v1
uses: gradle/wrapper-validation-action@v2
- name: Setup Android SDK
run: |
@ -32,10 +32,11 @@ jobs:
java-version: 17
distribution: adopt
- name: Set up gradle
uses: gradle/actions/setup-gradle@v3
- name: Build app and run unit tests
uses: gradle/gradle-command-action@v2
with:
arguments: detekt assembleStandardRelease testReleaseUnitTest
run: ./gradlew detekt assembleStandardRelease testReleaseUnitTest
# Sign APK and create release for tags

View File

@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Moderate issues
uses: tachiyomiorg/issue-moderator-action@v2
uses: tachiyomiorg/issue-moderator-action@v2.6.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
duplicate-label: Duplicate

View File

@ -208,7 +208,7 @@ dependencies {
// Disk
implementation(libs.disklrucache)
implementation(libs.unifile)
implementation(libs.junrar)
implementation(libs.bundles.archive)
// Preferences
implementation(libs.preferencektx)

View File

@ -72,6 +72,9 @@
# XmlUtil
-keep public enum nl.adaptivity.xmlutil.EventType { *; }
# Apache Commons Compress
-keep class * extends org.apache.commons.compress.archivers.zip.ZipExtraField { <init>(); }
# Firebase
-keep class com.google.firebase.installations.** { *; }
-keep interface com.google.firebase.installations.** { *; }

View File

@ -17,7 +17,6 @@ import eu.kanade.tachiyomi.util.system.isRunning
import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority
import tachiyomi.core.common.util.system.logcat
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit

View File

@ -327,9 +327,11 @@ class SyncManager(
}
/**
* Filters the favorite and non-favorite manga from the backup and checks if the favorite manga is different from the local database.
* Filters the favorite and non-favorite manga from the backup and checks
* if the favorite manga is different from the local database.
* @param backup the Backup object containing the backup data.
* @return a Pair of lists, where the first list contains different favorite manga and the second list contains non-favorite manga.
* @return a Pair of lists, where the first list contains different favorite manga
* and the second list contains non-favorite manga.
*/
private suspend fun filterFavoritesAndNonFavorites(backup: Backup): Pair<List<BackupManga>, List<BackupManga>> {
val favorites = mutableListOf<BackupManga>()

View File

@ -354,8 +354,10 @@ class GoogleDriveService(private val context: Context) {
}
/**
* Generates the authorization URL required for the user to grant the application permission to access their Google Drive account.
* Sets the approval prompt to "force" to ensure that the user is always prompted to grant access, even if they have previously granted access.
* Generates the authorization URL required for the user to grant the application
* permission to access their Google Drive account.
* Sets the approval prompt to "force" to ensure that the user is always prompted to grant access,
* even if they have previously granted access.
* @return The authorization URL.
*/
private fun generateAuthorizationUrl(): String {

View File

@ -158,12 +158,13 @@ class SyncYomiSyncService(
val host = syncPreferences.clientHost().get()
val apiKey = syncPreferences.clientAPIKey().get()
val uploadUrl = "$host/api/sync/upload"
val timeout = 30L
// Set timeout to 30 seconds
val client = OkHttpClient.Builder()
.connectTimeout(30, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS)
.writeTimeout(30, TimeUnit.SECONDS)
.connectTimeout(timeout, TimeUnit.SECONDS)
.readTimeout(timeout, TimeUnit.SECONDS)
.writeTimeout(timeout, TimeUnit.SECONDS)
.build()
val headers = Headers.Builder().add(

View File

@ -28,7 +28,6 @@ import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion
import nl.adaptivity.xmlutil.serialization.XML
import tachiyomi.core.common.storage.AndroidStorageFolderProvider
import tachiyomi.core.common.storage.UniFileTempFileManager
import tachiyomi.data.AndroidDatabaseHandler
import tachiyomi.data.Database
import tachiyomi.data.DatabaseHandler
@ -113,8 +112,6 @@ class AppModule(val app: Application) : InjektModule {
ProtoBuf
}
addSingletonFactory { UniFileTempFileManager(app) }
addSingletonFactory { ChapterCache(app, get()) }
addSingletonFactory { CoverCache(app) }

View File

@ -57,7 +57,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.runBlocking
import logcat.LogPriority
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.launchNonCancellable
import tachiyomi.core.common.util.lang.withIOContext
@ -88,7 +87,6 @@ class ReaderViewModel @JvmOverloads constructor(
private val sourceManager: SourceManager = Injekt.get(),
private val downloadManager: DownloadManager = Injekt.get(),
private val downloadProvider: DownloadProvider = Injekt.get(),
private val tempFileManager: UniFileTempFileManager = Injekt.get(),
private val imageSaver: ImageSaver = Injekt.get(),
preferences: BasePreferences = Injekt.get(),
val readerPreferences: ReaderPreferences = Injekt.get(),
@ -274,7 +272,7 @@ class ReaderViewModel @JvmOverloads constructor(
val context = Injekt.get<Application>()
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 })
Result.success(true)
@ -922,7 +920,6 @@ class ReaderViewModel @JvmOverloads constructor(
private fun deletePendingChapters() {
viewModelScope.launchNonCancellable {
downloadManager.deletePendingChapters()
tempFileManager.deleteTempFiles()
}
}

View File

@ -8,7 +8,7 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
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.system.logcat
import tachiyomi.domain.manga.model.Manga
@ -24,7 +24,6 @@ class ChapterLoader(
private val context: Context,
private val downloadManager: DownloadManager,
private val downloadProvider: DownloadProvider,
private val tempFileManager: UniFileTempFileManager,
private val manga: Manga,
private val source: Source,
) {
@ -92,18 +91,17 @@ class ChapterLoader(
source,
downloadManager,
downloadProvider,
tempFileManager,
)
source is LocalSource -> source.getFormat(chapter.chapter).let { format ->
when (format) {
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 {
RarPageLoader(tempFileManager.createTempFile(format.file))
RarPageLoader(format.file.openInputStream())
} catch (e: UnsupportedRarV5Exception) {
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)

View File

@ -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 tachiyomi.core.common.storage.UniFileTempFileManager
import tachiyomi.core.common.storage.openReadOnlyChannel
import tachiyomi.domain.manga.model.Manga
import uy.kohesive.injekt.injectLazy
@ -23,7 +23,6 @@ internal class DownloadPageLoader(
private val source: Source,
private val downloadManager: DownloadManager,
private val downloadProvider: DownloadProvider,
private val tempFileManager: UniFileTempFileManager,
) : PageLoader() {
private val context: Application by injectLazy()
@ -48,7 +47,7 @@ internal class DownloadPageLoader(
}
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()
}

View File

@ -3,14 +3,14 @@ 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 java.io.File
import java.nio.channels.SeekableByteChannel
/**
* 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

View File

@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder
import tachiyomi.core.common.util.system.ImageUtil
import java.io.File
import java.io.InputStream
import java.io.PipedInputStream
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.
*/
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

View File

@ -3,22 +3,21 @@ 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 org.apache.commons.compress.archivers.zip.ZipFile
import tachiyomi.core.common.util.system.ImageUtil
import java.io.File
import java.nio.charset.StandardCharsets
import java.util.zip.ZipFile
import java.nio.channels.SeekableByteChannel
/**
* 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 suspend fun getPages(): List<ReaderPage> {
return zip.entries().asSequence()
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 ->

View File

@ -32,6 +32,7 @@ dependencies {
implementation(libs.image.decoder)
implementation(libs.unifile)
implementation(libs.bundles.archive)
api(kotlinx.coroutines.core)
api(kotlinx.serialization.json)

View File

@ -1,22 +1,23 @@
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.nodes.Document
import java.io.Closeable
import java.io.File
import java.io.InputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipFile
import java.nio.channels.SeekableByteChannel
/**
* Wrapper over ZipFile to load files in epub format.
*/
class EpubFile(file: File) : Closeable {
class EpubFile(channel: SeekableByteChannel) : Closeable {
/**
* Zip file of this epub.
*/
private val zip = ZipFile(file)
private val zip = ZipFile(channel)
/**
* 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.
*/
fun getInputStream(entry: ZipEntry): InputStream {
fun getInputStream(entry: ZipArchiveEntry): InputStream {
return zip.getInputStream(entry)
}
/**
* 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)
}

View File

@ -1,6 +1,9 @@
package tachiyomi.core.common.storage
import android.content.Context
import android.os.ParcelFileDescriptor
import com.hippo.unifile.UniFile
import java.nio.channels.FileChannel
val UniFile.extension: String?
get() = name?.substringAfterLast('.')
@ -10,3 +13,7 @@ val UniFile.nameWithoutExtension: String?
val UniFile.displayablePath: String
get() = filePath ?: uri.toString()
fun UniFile.openReadOnlyChannel(context: Context): FileChannel {
return ParcelFileDescriptor.AutoCloseInputStream(context.contentResolver.openFileDescriptor(uri, "r")).channel
}

View File

@ -1,46 +0,0 @@
package tachiyomi.core.common.storage
import android.content.Context
import android.os.Build
import android.os.FileUtils
import com.hippo.unifile.UniFile
import java.io.BufferedOutputStream
import java.io.File
class UniFileTempFileManager(
private val context: Context,
) {
private val dir = File(context.externalCacheDir, "tmp")
fun createTempFile(file: UniFile): File {
dir.mkdirs()
val inputStream = context.contentResolver.openInputStream(file.uri)!!
val tempFile = File.createTempFile(
file.nameWithoutExtension.orEmpty().padEnd(3), // Prefix must be 3+ chars
null,
dir,
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
FileUtils.copy(inputStream, tempFile.outputStream())
} else {
BufferedOutputStream(tempFile.outputStream()).use { tmpOut ->
inputStream.use { input ->
val buffer = ByteArray(8192)
var count: Int
while (input.read(buffer).also { count = it } > 0) {
tmpOut.write(buffer, 0, count)
}
}
}
}
return tempFile
}
fun deleteTempFiles() {
dir.deleteRecursively()
}
}

View File

@ -32,6 +32,7 @@ jsoup = "org.jsoup:jsoup:1.17.2"
disklrucache = "com.jakewharton:disklrucache:2.0.2"
unifile = "com.github.tachiyomiorg:unifile:7c257e1c64"
common-compress = "org.apache.commons:commons-compress:1.25.0"
junrar = "com.github.junrar:junrar:7.5.5"
sqlite-framework = { module = "androidx.sqlite:sqlite-framework", version.ref = "sqlite" }
@ -103,6 +104,7 @@ google-api-services-drive = "com.google.apis:google-api-services-drive:v3-rev197
google-api-client-oauth = "com.google.oauth-client:google-oauth-client:1.34.1"
[bundles]
archive = ["common-compress", "junrar"]
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]
js-engine = ["quickjs-android"]
sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"]

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

View File

@ -12,7 +12,7 @@ kotlin {
api(projects.i18n)
implementation(libs.unifile)
implementation(libs.junrar)
implementation(libs.bundles.archive)
}
}
val androidMain by getting {

View File

@ -18,15 +18,16 @@ import kotlinx.serialization.json.decodeFromStream
import logcat.LogPriority
import nl.adaptivity.xmlutil.AndroidXmlReader
import nl.adaptivity.xmlutil.serialization.XML
import org.apache.commons.compress.archivers.zip.ZipFile
import tachiyomi.core.common.i18n.stringResource
import tachiyomi.core.metadata.comicinfo.COMIC_INFO_FILE
import tachiyomi.core.metadata.comicinfo.ComicInfo
import tachiyomi.core.metadata.comicinfo.copyFromComicInfo
import tachiyomi.core.metadata.comicinfo.getComicInfo
import tachiyomi.core.metadata.tachiyomi.MangaDetails
import tachiyomi.core.common.storage.UniFileTempFileManager
import tachiyomi.core.common.storage.extension
import tachiyomi.core.common.storage.nameWithoutExtension
import tachiyomi.core.common.storage.openReadOnlyChannel
import tachiyomi.core.common.util.lang.withIOContext
import tachiyomi.core.common.util.system.ImageUtil
import tachiyomi.core.common.util.system.logcat
@ -40,10 +41,8 @@ import tachiyomi.source.local.io.Format
import tachiyomi.source.local.io.LocalSourceFileSystem
import tachiyomi.source.local.metadata.fillMetadata
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.io.InputStream
import java.nio.charset.StandardCharsets
import java.util.zip.ZipFile
import kotlin.time.Duration.Companion.days
import com.github.junrar.Archive as JunrarArchive
import tachiyomi.domain.source.model.Source as DomainSource
@ -56,7 +55,6 @@ actual class LocalSource(
private val json: Json by injectLazy()
private val xml: XML by injectLazy()
private val tempFileManager: UniFileTempFileManager by injectLazy()
private val POPULAR_FILTERS = FilterList(OrderBy.Popular(context))
private val LATEST_FILTERS = FilterList(OrderBy.Latest(context))
@ -146,8 +144,8 @@ actual class LocalSource(
// Augment manga details based on metadata files
try {
val mangaDir by lazy { fileSystem.getMangaDirectory(manga.url) }
val mangaDirFiles = fileSystem.getFilesInMangaDirectory(manga.url)
val mangaDir = fileSystem.getMangaDirectory(manga.url) ?: error("${manga.url} is not a valid directory")
val mangaDirFiles = mangaDir.listFiles().orEmpty()
val comicInfoFile = mangaDirFiles
.firstOrNull { it.name == COMIC_INFO_FILE }
@ -177,7 +175,7 @@ actual class LocalSource(
// Replace with ComicInfo.xml file
val comicInfo = manga.getComicInfo()
mangaDir
?.createFile(COMIC_INFO_FILE)
.createFile(COMIC_INFO_FILE)
?.openOutputStream()
?.use {
val comicInfoString = xml.encodeToString(ComicInfo.serializer(), comicInfo)
@ -192,14 +190,12 @@ actual class LocalSource(
.filter(Archive::isSupported)
.toList()
val folderPath = mangaDir?.filePath
val copiedFile = copyComicInfoFileFromArchive(chapterArchives, folderPath)
val copiedFile = copyComicInfoFileFromArchive(chapterArchives, mangaDir)
if (copiedFile != null) {
setMangaDetailsFromComicInfoFile(copiedFile.inputStream(), manga)
setMangaDetailsFromComicInfoFile(copiedFile.openInputStream(), manga)
} else {
// Avoid re-scanning
mangaDir?.createFile(".noxml")
mangaDir.createFile(".noxml")
}
}
}
@ -210,23 +206,23 @@ actual class LocalSource(
return@withIOContext manga
}
private fun copyComicInfoFileFromArchive(chapterArchives: List<UniFile>, folderPath: String?): File? {
private fun copyComicInfoFileFromArchive(chapterArchives: List<UniFile>, folder: UniFile): UniFile? {
for (chapter in chapterArchives) {
when (Format.valueOf(chapter)) {
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.getInputStream(comicInfoFile).buffered().use { stream ->
return copyComicInfoFile(stream, folderPath)
return copyComicInfoFile(stream, folder)
}
}
}
}
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.getInputStream(comicInfoFile).buffered().use { stream ->
return copyComicInfoFile(stream, folderPath)
return copyComicInfoFile(stream, folder)
}
}
}
@ -237,9 +233,9 @@ actual class LocalSource(
return null
}
private fun copyComicInfoFile(comicInfoFileStream: InputStream, folderPath: String?): File {
return File("$folderPath/$COMIC_INFO_FILE").apply {
outputStream().use { outputStream ->
private fun copyComicInfoFile(comicInfoFileStream: InputStream, folder: UniFile): UniFile? {
return folder.createFile(COMIC_INFO_FILE)?.apply {
openOutputStream().use { outputStream ->
comicInfoFileStream.use { it.copyTo(outputStream) }
}
}
@ -273,7 +269,7 @@ actual class LocalSource(
val format = Format.valueOf(chapterFile)
if (format is Format.Epub) {
EpubFile(tempFileManager.createTempFile(format.file)).use { epub ->
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
epub.fillMetadata(manga, this)
}
}
@ -332,8 +328,8 @@ actual class LocalSource(
entry?.let { coverManager.update(manga, it.openInputStream()) }
}
is Format.Zip -> {
ZipFile(tempFileManager.createTempFile(format.file)).use { zip ->
val entry = zip.entries().toList()
ZipFile(format.file.openReadOnlyChannel(context)).use { zip ->
val entry = zip.entries.toList()
.sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
.find { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
@ -341,7 +337,7 @@ actual class LocalSource(
}
}
is Format.Rar -> {
JunrarArchive(tempFileManager.createTempFile(format.file)).use { archive ->
JunrarArchive(format.file.openInputStream()).use { archive ->
val entry = archive.fileHeaders
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
.find { !it.isDirectory && ImageUtil.isImage(it.fileName) { archive.getInputStream(it) } }
@ -350,7 +346,7 @@ actual class LocalSource(
}
}
is Format.Epub -> {
EpubFile(tempFileManager.createTempFile(format.file)).use { epub ->
EpubFile(format.file.openReadOnlyChannel(context)).use { epub ->
val entry = epub.getImagesFromPages()
.firstOrNull()
?.let { epub.getEntry(it) }

View File

@ -22,9 +22,6 @@ actual class LocalSourceFileSystem(
}
actual fun getFilesInMangaDirectory(name: String): List<UniFile> {
return getBaseDirectory()
?.findFile(name, true)
?.takeIf { it.isDirectory }
?.listFiles().orEmpty().toList()
return getMangaDirectory(name)?.listFiles().orEmpty().toList()
}
}