Files
TachiyomiSY/source-local/src/androidMain/kotlin/tachiyomi/source/local/image/LocalCoverManager.kt
T
arkon ab63f6036c Remove storage permissions
Requires adjusting some file reading to first copy to a temporary file
in cache that we have permissions to read from. This is only applicable for things
like ZIP files where we need an actual File rather than just some Android content
URI shenanigans.

(cherry picked from commit 4fcdde4913df28bbd678ae1be4a2971ed77179d3)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt
#	source-local/src/androidMain/kotlin/tachiyomi/source/local/LocalSource.kt
2023-12-24 11:46:47 -05:00

96 lines
3.2 KiB
Kotlin

package tachiyomi.source.local.image
import android.content.Context
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.storage.CbzCrypto
import eu.kanade.tachiyomi.util.storage.DiskUtil
import net.lingala.zip4j.ZipFile
import net.lingala.zip4j.model.ZipParameters
import tachiyomi.core.storage.nameWithoutExtension
import tachiyomi.core.util.system.ImageUtil
import tachiyomi.source.local.io.LocalSourceFileSystem
import java.io.File
import java.io.InputStream
private const val DEFAULT_COVER_NAME = "cover.jpg"
private const val COVER_ARCHIVE_NAME = "cover.cbi"
actual class LocalCoverManager(
private val context: Context,
private val fileSystem: LocalSourceFileSystem,
) {
actual fun find(mangaUrl: String): UniFile? {
return fileSystem.getFilesInMangaDirectory(mangaUrl)
// Get all file whose names start with "cover"
.filter { it.isFile && it.nameWithoutExtension.equals("cover", ignoreCase = true) }
// Get the first actual image
.firstOrNull {
ImageUtil.isImage(it.name) { it.openInputStream() } || it.name == COVER_ARCHIVE_NAME
}
}
actual fun update(
manga: SManga,
inputStream: InputStream,
// SY -->
encrypted: Boolean,
// SY <--
): UniFile? {
val directory = fileSystem.getMangaDirectory(manga.url)
if (directory == null) {
inputStream.close()
return null
}
var targetFile = find(manga.url)
if (targetFile == null) {
// SY -->
targetFile = if (encrypted) {
directory.createFile(COVER_ARCHIVE_NAME)
} else {
directory.createFile(DEFAULT_COVER_NAME)
}
// SY <--
}
targetFile!!
inputStream.use { input ->
// SY -->
if (encrypted) {
val tempFile = File.createTempFile(
targetFile.nameWithoutExtension.orEmpty(),
null,
)
val zip4j = ZipFile(tempFile)
val zipParameters = ZipParameters()
zip4j.setPassword(CbzCrypto.getDecryptedPasswordCbz())
CbzCrypto.setZipParametersEncrypted(zipParameters)
zipParameters.fileNameInZip = DEFAULT_COVER_NAME
zip4j.addStream(input, zipParameters)
zip4j.close()
targetFile.openOutputStream().use { output ->
tempFile.inputStream().use { input ->
input.copyTo(output)
}
}
DiskUtil.createNoMediaFile(directory, context)
manga.thumbnail_url = targetFile.uri.toString()
return targetFile
} else {
// SY <--
targetFile.openOutputStream().use { output ->
input.copyTo(output)
}
DiskUtil.createNoMediaFile(directory, context)
manga.thumbnail_url = targetFile.uri.toString()
return targetFile
}
}
}
}