Copy cleanup orphaned downloads from J2k

This commit is contained in:
Jobobby04 2020-08-06 14:59:31 -04:00
parent 2de87f8d29
commit 0125f326b4
5 changed files with 126 additions and 0 deletions

View File

@ -200,6 +200,18 @@ class DownloadCache(
}
}
// SY -->
fun removeFolders(folders: List<String>, manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return
for (chapter in folders) {
if (chapter in mangaDir.files) {
mangaDir.files -= chapter
}
}
}
// SY <--
/**
* Removes a list of chapters that have been deleted from this cache.
*

View File

@ -209,6 +209,32 @@ class DownloadManager(/* SY private */ val context: Context) {
}
}
// SY -->
/**
* Deletes the directories of chapters that were read or have no match
*
* @param chapters the list of chapters to delete.
* @param manga the manga of the chapters.
* @param source the source of the chapters.
*/
fun cleanupChapters(allChapters: List<Chapter>, manga: Manga, source: Source): Int {
var cleaned = 0
val filesWithNoChapter = provider.findUnmatchedChapterDirs(allChapters, manga, source)
cleaned += filesWithNoChapter.size
cache.removeFolders(filesWithNoChapter.mapNotNull { it.name }, manga)
filesWithNoChapter.forEach { it.delete() }
val readChapters = allChapters.filter { it.read }
val readChapterDirs = provider.findChapterDirs(readChapters, manga, source)
readChapterDirs.forEach { it.delete() }
cleaned += readChapterDirs.size
cache.removeChapters(readChapters, manga)
if (cache.getDownloadCount(manga) == 0) {
provider.findChapterDirs(allChapters, manga, source).firstOrNull()?.parentFile?.delete() // Delete manga directory if empty
}
return cleaned
}
// SY <--
/**
* Deletes the directory of a downloaded manga.
*

View File

@ -109,6 +109,32 @@ class DownloadProvider(private val context: Context) {
}
}
// SY -->
/**
* Returns a list of all files in manga directory
*
* @param chapters the chapters to query.
* @param manga the manga of the chapter.
* @param source the source of the chapter.
*/
fun findUnmatchedChapterDirs(
chapters: List<Chapter>,
manga: Manga,
source: Source
): List<UniFile> {
val mangaDir = findMangaDir(manga, source) ?: return emptyList()
return mangaDir.listFiles()!!.asList().filter {
(
chapters.find { chp ->
getValidChapterDirNames(chp).any { dir ->
mangaDir.findFile(dir) != null
}
} == null
) || it.name?.endsWith("_tmp") == true
}
}
// SY <--
/**
* Returns the download directory name for a source.
*

View File

@ -7,6 +7,7 @@ import android.content.Intent
import android.os.Build
import android.os.Bundle
import android.provider.Settings
import android.widget.Toast
import androidx.core.net.toUri
import androidx.core.text.HtmlCompat
import androidx.preference.PreferenceScreen
@ -14,13 +15,16 @@ import com.afollestad.materialdialogs.MaterialDialog
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.SourceManager.Companion.DELEGATED_SOURCES
import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.intListPreference
import eu.kanade.tachiyomi.util.preference.onChange
@ -42,9 +46,16 @@ import exh.PERV_EDEN_IT_SOURCE_ID
import exh.debug.SettingsDebugController
import exh.log.EHLogLevel
import exh.source.BlacklistedSources
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import rx.Observable
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
class SettingsAdvancedController : SettingsController() {
@ -141,6 +152,17 @@ class SettingsAdvancedController : SettingsController() {
}
// --> EXH
preferenceCategory {
titleRes = R.string.group_downloader
preference {
titleRes = R.string.clean_up_downloaded_chapters
summaryRes = R.string.delete_unused_chapters
onClick { cleanupDownloads() }
}
}
preferenceCategory {
titleRes = R.string.developer_tools
isPersistent = false
@ -237,6 +259,35 @@ class SettingsAdvancedController : SettingsController() {
// <-- EXH
}
// SY -->
private fun cleanupDownloads() {
if (job?.isActive == true) return
activity?.toast(R.string.starting_cleanup)
job = GlobalScope.launch(Dispatchers.IO, CoroutineStart.DEFAULT) {
val mangaList = db.getMangas().executeAsBlocking()
val sourceManager: SourceManager = Injekt.get()
val downloadManager: DownloadManager = Injekt.get()
var foldersCleared = 0
for (manga in mangaList) {
val chapterList = db.getChapters(manga).executeAsBlocking()
val source = sourceManager.getOrStub(manga.source)
foldersCleared += downloadManager.cleanupChapters(chapterList, manga, source)
}
launchUI {
val activity = activity ?: return@launchUI
val cleanupString =
if (foldersCleared == 0) activity.getString(R.string.no_folders_to_cleanup)
else resources!!.getQuantityString(
R.plurals.cleanup_done,
foldersCleared,
foldersCleared
)
activity.toast(cleanupString, Toast.LENGTH_LONG)
}
}
}
// SY <--
private fun clearChapterCache() {
if (activity == null) return
val files = chapterCache.cacheDir.listFiles() ?: return
@ -281,5 +332,7 @@ class SettingsAdvancedController : SettingsController() {
private companion object {
const val CLEAR_CACHE_KEY = "pref_clear_cache_key"
private var job: Job? = null
}
}

View File

@ -126,6 +126,14 @@
<string name="enable_source_blacklist_summary">Hide extensions/sources that are incompatible with %1$s. Force-restart app after changing.</string>
<string name="open_debug_menu">Open debug menu</string>
<string name="open_debug_menu_summary"><![CDATA[DO NOT TOUCH THIS MENU UNLESS YOU KNOW WHAT YOU ARE DOING! <font color=\'red\'>IT CAN CORRUPT YOUR LIBRARY!</font>]]></string>
<string name="starting_cleanup">Starting cleanup</string>
<string name="clean_up_downloaded_chapters">Clean up downloaded chapters</string>
<string name="delete_unused_chapters">Delete non-existent, partially downloaded, and read chapter folders</string>
<string name="no_folders_to_cleanup">No folders to cleanup</string>
<plurals name="cleanup_done">
<item quantity="one">Cleanup done. Removed %d folder</item>
<item quantity="other">Cleanup done. Removed %d folders</item>
</plurals>
<!-- Log Level -->
<string name="log_minimal">Minimal</string>
@ -178,6 +186,7 @@
<string name="preserve_reading_position">Preserve reading position on read manga</string>
<string name="auto_webtoon_mode">Auto Webtoon Mode</string>
<string name="auto_webtoon_mode_summary">Use auto webtoon mode for manga that are detected to likely use the long strip format</string>
<string name="enable_zoom_out">Enable zoom out</string>
<!-- Reader -->
<!-- Reader Actions -->