Add compress to CBZ on download (#6360)
This commit is contained in:
parent
22615f5981
commit
5336c5b46e
@ -143,7 +143,7 @@ class DownloadCache(
|
|||||||
mangaDirs.values.forEach { mangaDir ->
|
mangaDirs.values.forEach { mangaDir ->
|
||||||
val chapterDirs = mangaDir.dir.listFiles()
|
val chapterDirs = mangaDir.dir.listFiles()
|
||||||
.orEmpty()
|
.orEmpty()
|
||||||
.mapNotNull { it.name }
|
.mapNotNull { it.name?.replace(".cbz", "") }
|
||||||
.toHashSet()
|
.toHashSet()
|
||||||
|
|
||||||
mangaDir.files = chapterDirs
|
mangaDir.files = chapterDirs
|
||||||
|
@ -39,7 +39,7 @@ class DownloadManager(
|
|||||||
/**
|
/**
|
||||||
* Downloads provider, used to retrieve the folders where the chapters are or should be stored.
|
* Downloads provider, used to retrieve the folders where the chapters are or should be stored.
|
||||||
*/
|
*/
|
||||||
private val provider = DownloadProvider(context)
|
val provider = DownloadProvider(context)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of downloaded chapters.
|
* Cache of downloaded chapters.
|
||||||
|
@ -148,10 +148,14 @@ class DownloadProvider(private val context: Context) {
|
|||||||
* @param chapter the chapter to query.
|
* @param chapter the chapter to query.
|
||||||
*/
|
*/
|
||||||
fun getValidChapterDirNames(chapter: Chapter): List<String> {
|
fun getValidChapterDirNames(chapter: Chapter): List<String> {
|
||||||
|
val chapterName = getChapterDirName(chapter)
|
||||||
return listOf(
|
return listOf(
|
||||||
getChapterDirName(chapter),
|
// Folder of images
|
||||||
|
chapterName,
|
||||||
|
|
||||||
|
// Archived chapters
|
||||||
|
"$chapterName.cbz",
|
||||||
|
|
||||||
// TODO: remove this
|
|
||||||
// Legacy chapter directory name used in v0.9.2 and before
|
// Legacy chapter directory name used in v0.9.2 and before
|
||||||
DiskUtil.buildValidFilename(chapter.name)
|
DiskUtil.buildValidFilename(chapter.name)
|
||||||
)
|
)
|
||||||
|
@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.data.database.models.Chapter
|
|||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.model.Download
|
import eu.kanade.tachiyomi.data.download.model.Download
|
||||||
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
import eu.kanade.tachiyomi.data.download.model.DownloadQueue
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.UnmeteredSource
|
import eu.kanade.tachiyomi.source.UnmeteredSource
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
@ -35,7 +36,11 @@ import rx.android.schedulers.AndroidSchedulers
|
|||||||
import rx.schedulers.Schedulers
|
import rx.schedulers.Schedulers
|
||||||
import rx.subscriptions.CompositeSubscription
|
import rx.subscriptions.CompositeSubscription
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.io.BufferedOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.util.zip.CRC32
|
||||||
|
import java.util.zip.ZipEntry
|
||||||
|
import java.util.zip.ZipOutputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class is the one in charge of downloading chapters.
|
* This class is the one in charge of downloading chapters.
|
||||||
@ -60,6 +65,8 @@ class Downloader(
|
|||||||
|
|
||||||
private val chapterCache: ChapterCache by injectLazy()
|
private val chapterCache: ChapterCache by injectLazy()
|
||||||
|
|
||||||
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Store for persisting downloads across restarts.
|
* Store for persisting downloads across restarts.
|
||||||
*/
|
*/
|
||||||
@ -484,13 +491,51 @@ class Downloader(
|
|||||||
|
|
||||||
// Only rename the directory if it's downloaded.
|
// Only rename the directory if it's downloaded.
|
||||||
if (download.status == Download.State.DOWNLOADED) {
|
if (download.status == Download.State.DOWNLOADED) {
|
||||||
|
if (preferences.saveChaptersAsCBZ().get()) {
|
||||||
|
archiveChapter(mangaDir, dirname, tmpDir)
|
||||||
|
} else {
|
||||||
tmpDir.renameTo(dirname)
|
tmpDir.renameTo(dirname)
|
||||||
|
}
|
||||||
cache.addChapter(dirname, mangaDir, download.manga)
|
cache.addChapter(dirname, mangaDir, download.manga)
|
||||||
|
|
||||||
DiskUtil.createNoMediaFile(tmpDir, context)
|
DiskUtil.createNoMediaFile(tmpDir, context)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archive the chapter pages as a CBZ.
|
||||||
|
*/
|
||||||
|
private fun archiveChapter(
|
||||||
|
mangaDir: UniFile,
|
||||||
|
dirname: String,
|
||||||
|
tmpDir: UniFile,
|
||||||
|
) {
|
||||||
|
val zip = mangaDir.createFile("$dirname.cbz.tmp")
|
||||||
|
ZipOutputStream(BufferedOutputStream(zip.openOutputStream())).use { zipOut ->
|
||||||
|
zipOut.setMethod(ZipEntry.STORED)
|
||||||
|
|
||||||
|
tmpDir.listFiles()?.forEach { img ->
|
||||||
|
img.openInputStream().use { input ->
|
||||||
|
val data = input.readBytes()
|
||||||
|
val size = img.length()
|
||||||
|
val entry = ZipEntry(img.name).apply {
|
||||||
|
val crc = CRC32().apply {
|
||||||
|
update(data)
|
||||||
|
}
|
||||||
|
setCrc(crc.value)
|
||||||
|
|
||||||
|
compressedSize = size
|
||||||
|
setSize(size)
|
||||||
|
}
|
||||||
|
zipOut.putNextEntry(entry)
|
||||||
|
zipOut.write(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
zip.renameTo("$dirname.cbz")
|
||||||
|
tmpDir.delete()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completes a download. This method is called in the main thread.
|
* Completes a download. This method is called in the main thread.
|
||||||
*/
|
*/
|
||||||
|
@ -202,6 +202,8 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun downloadOnlyOverWifi() = prefs.getBoolean(Keys.downloadOnlyOverWifi, true)
|
fun downloadOnlyOverWifi() = prefs.getBoolean(Keys.downloadOnlyOverWifi, true)
|
||||||
|
|
||||||
|
fun saveChaptersAsCBZ() = flowPrefs.getBoolean("save_chapter_as_cbz", false)
|
||||||
|
|
||||||
fun folderPerManga() = prefs.getBoolean(Keys.folderPerManga, false)
|
fun folderPerManga() = prefs.getBoolean(Keys.folderPerManga, false)
|
||||||
|
|
||||||
fun numberOfBackups() = flowPrefs.getInt("backup_slots", 1)
|
fun numberOfBackups() = flowPrefs.getInt("backup_slots", 1)
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.reader.loader
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||||
import eu.kanade.tachiyomi.source.Source
|
import eu.kanade.tachiyomi.source.Source
|
||||||
@ -10,6 +11,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
|||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loader used to load a chapter from the downloaded chapters.
|
* Loader used to load a chapter from the downloaded chapters.
|
||||||
@ -28,6 +30,20 @@ class DownloadPageLoader(
|
|||||||
* Returns an observable containing the pages found on this downloaded chapter.
|
* Returns an observable containing the pages found on this downloaded chapter.
|
||||||
*/
|
*/
|
||||||
override fun getPages(): Observable<List<ReaderPage>> {
|
override fun getPages(): Observable<List<ReaderPage>> {
|
||||||
|
val chapterPath = downloadManager.provider.findChapterDir(chapter.chapter, manga, source)
|
||||||
|
return if (chapterPath?.isFile == true) {
|
||||||
|
getPagesFromArchive(chapterPath)
|
||||||
|
} else {
|
||||||
|
getPagesFromDirectory()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPagesFromArchive(chapterPath: UniFile): Observable<List<ReaderPage>> {
|
||||||
|
val loader = ZipPageLoader(File(chapterPath.filePath!!))
|
||||||
|
return loader.getPages()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getPagesFromDirectory(): Observable<List<ReaderPage>> {
|
||||||
return downloadManager.buildPageList(source, manga, chapter.chapter)
|
return downloadManager.buildPageList(source, manga, chapter.chapter)
|
||||||
.map { pages ->
|
.map { pages ->
|
||||||
pages.map { page ->
|
pages.map { page ->
|
||||||
|
@ -68,6 +68,10 @@ class SettingsDownloadController : SettingsController() {
|
|||||||
titleRes = R.string.connected_to_wifi
|
titleRes = R.string.connected_to_wifi
|
||||||
defaultValue = true
|
defaultValue = true
|
||||||
}
|
}
|
||||||
|
switchPreference {
|
||||||
|
bindTo(preferences.saveChaptersAsCBZ())
|
||||||
|
titleRes = R.string.save_chapter_as_cbz
|
||||||
|
}
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
titleRes = R.string.pref_category_delete_chapters
|
titleRes = R.string.pref_category_delete_chapters
|
||||||
|
|
||||||
|
@ -398,6 +398,7 @@
|
|||||||
<string name="pref_category_auto_download">Auto-download</string>
|
<string name="pref_category_auto_download">Auto-download</string>
|
||||||
<string name="pref_download_new">Download new chapters</string>
|
<string name="pref_download_new">Download new chapters</string>
|
||||||
<string name="pref_download_new_categories_details">Manga in excluded categories will not be downloaded even if they are also in included categories.</string>
|
<string name="pref_download_new_categories_details">Manga in excluded categories will not be downloaded even if they are also in included categories.</string>
|
||||||
|
<string name="save_chapter_as_cbz">Save as CBZ archive</string>
|
||||||
|
|
||||||
<!-- Tracking section -->
|
<!-- Tracking section -->
|
||||||
<string name="tracking_guide">Tracking guide</string>
|
<string name="tracking_guide">Tracking guide</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user