Copy cleanup orphaned downloads from J2k
This commit is contained in:
parent
2de87f8d29
commit
0125f326b4
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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 -->
|
||||
|
Loading…
x
Reference in New Issue
Block a user