Reworking cache logic

This commit is contained in:
Jay 2020-02-04 00:36:10 -08:00
parent 723cf74b6d
commit fda8a85882
4 changed files with 57 additions and 82 deletions

View File

@ -3,16 +3,16 @@ package eu.kanade.tachiyomi.data.download
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter 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.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.util.DiskUtil import eu.kanade.tachiyomi.util.DiskUtil
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.File import uy.kohesive.injekt.injectLazy
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
@ -47,14 +47,15 @@ class DownloadCache(
/** /**
* The root directory for downloads. * The root directory for downloads.
*/ */
private var rootDir = RootDirectory(getDirectoryFromPreference()) //private var rootDir = RootDirectory(getDirectoryFromPreference())
private var mangaFiles: MutableMap<Long, MutableSet<String>> = mutableMapOf()
init { init {
preferences.downloadsDirectory().asObservable() preferences.downloadsDirectory().asObservable()
.skip(1) .skip(1)
.subscribe { .subscribe {
lastRenew = 0L // invalidate cache lastRenew = 0L // invalidate cache
rootDir = RootDirectory(getDirectoryFromPreference()) //rootDir = RootDirectory(getDirectoryFromPreference())
} }
} }
@ -81,14 +82,8 @@ class DownloadCache(
checkRenew() checkRenew()
val sourceDir = rootDir.files[manga.source] val files = mangaFiles[manga.id] ?: return false
if (sourceDir != null) { return files.any { it in provider.getValidChapterDirNames(chapter) }
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)]
if (mangaDir != null) {
return mangaDir.files.any { it in provider.getValidChapterDirNames(chapter) }
}
}
return false
} }
/** /**
@ -99,16 +94,8 @@ class DownloadCache(
fun getDownloadCount(manga: Manga): Int { fun getDownloadCount(manga: Manga): Int {
checkRenew() checkRenew()
val sourceDir = rootDir.files[manga.source] val files = mangaFiles[manga.id] ?: return 0
if (sourceDir != null) { return files.filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) }.size
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)]
if (mangaDir != null) {
return mangaDir.files
.filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) }
.size
}
}
return 0
} }
/** /**
@ -128,30 +115,47 @@ class DownloadCache(
private fun renew() { private fun renew() {
val onlineSources = sourceManager.getOnlineSources() val onlineSources = sourceManager.getOnlineSources()
val sourceDirs = rootDir.dir.listFiles() val sourceDirs = getDirectoryFromPreference().listFiles()
.orEmpty() .orEmpty()
.associate { it.name to SourceDirectory(it) } .associate { it.name to SourceDirectory(it) }
.mapNotNullKeys { entry -> .mapNotNullKeys { entry ->
onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id onlineSources.find { provider.getSourceDirName(it) == entry.key }?.id
} }
//Timber.i("Sources: ${sourceDirs.map { it.value.dir.filePath }.joinToString(", ")}")
rootDir.files = sourceDirs //rootDir.files = sourceDirs
sourceDirs.values.forEach { sourceDir -> val db:DatabaseHelper by injectLazy()
val mangas = db.getLibraryMangas().executeAsBlocking()
sourceDirs.forEach { sourceValue ->
val sourceDir = sourceValue.value
val mangaDirs = sourceDir.dir.listFiles() val mangaDirs = sourceDir.dir.listFiles()
.orEmpty() .orEmpty()
.associateNotNullKeys { it.name to MangaDirectory(it) } .mapNotNull {
val name = it.name ?: return@mapNotNull null
name to MangaDirectory(it) }.toMap()
sourceDir.files = mangaDirs // Timber.i("${sourceDir.dir.name}: ${mangaDirs.map {
// it.key + " :: " + it.value.dir.filePath }.joinToString(", ")}")
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 }
.toHashSet() .toHashSet()
// Timber.i("${mangaDir.dir.name}: ${chapterDirs.joinToString(", ")}")
mangaDir.files = chapterDirs mangaDir.files = chapterDirs
} }
val trueMangaDirs = mangaDirs.mapNotNull { mangaDir ->
val manga = mangas.find { DiskUtil.buildValidFilename(it.originalTitle()) ==
mangaDir.key && it.source == sourceValue.key }
val id = manga?.id ?: return@mapNotNull null
id to mangaDir.value.files
}.toMap()
//sourceDir.files = trueMangaDirs
mangaFiles.putAll(trueMangaDirs)
} }
} }
@ -164,40 +168,14 @@ class DownloadCache(
*/ */
@Synchronized @Synchronized
fun addChapter(chapterDirName: String, mangaUniFile: UniFile, manga: Manga) { fun addChapter(chapterDirName: String, mangaUniFile: UniFile, manga: Manga) {
// Retrieve the cached source directory or cache a new one
var sourceDir = rootDir.files[manga.source] val id = manga.id ?: return
if (sourceDir == null) { val files = mangaFiles[id]
val source = sourceManager.get(manga.source) ?: return if (files == null) {
val sourceUniFile = provider.findSourceDir(source) ?: return mangaFiles[id] = mutableSetOf(chapterDirName)
sourceDir = SourceDirectory(sourceUniFile)
rootDir.files += manga.source to sourceDir
} }
else {
// Retrieve the cached manga directory or cache a new one mangaFiles[id]?.add(chapterDirName)
val mangaDirName = provider.getMangaDirName(manga)
var mangaDir = sourceDir.files[mangaDirName]
if (mangaDir == null) {
mangaDir = MangaDirectory(mangaUniFile)
sourceDir.files += mangaDirName to mangaDir
}
// Save the chapter directory
mangaDir.files += chapterDirName
}
/**
* Removes a chapter that has been deleted from this cache.
*
* @param chapter the chapter to remove.
* @param manga the manga of the chapter.
*/
@Synchronized
fun removeChapter(chapter: Chapter, manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return
val chapterDirName = provider.getChapterDirName(chapter)
if (chapterDirName in mangaDir.files) {
mangaDir.files -= chapterDirName
} }
} }
@ -209,29 +187,27 @@ class DownloadCache(
*/ */
@Synchronized @Synchronized
fun removeChapters(chapters: List<Chapter>, manga: Manga) { fun removeChapters(chapters: List<Chapter>, manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return val id = manga.id ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return
for (chapter in chapters) { for (chapter in chapters) {
val list = provider.getValidChapterDirNames(chapter) val list = provider.getValidChapterDirNames(chapter)
list.forEach { list.forEach {
if (it in mangaDir.files) { if (mangaFiles[id] != null && it in mangaFiles[id]!!) {
mangaDir.files -= it mangaFiles[id]?.remove(it)
} }
} }
} }
} }
fun removeFolders(folders: List<String>, manga: Manga) { fun removeFolders(folders: List<String>, manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return val id = manga.id ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return
for (chapter in folders) { for (chapter in folders) {
if (chapter in mangaDir.files) { if (mangaFiles[id] != null && chapter in mangaFiles[id]!!) {
mangaDir.files -= chapter mangaFiles[id]?.remove(chapter)
} }
} }
} }
fun renameFolder(from: String, to: String, source: Long) { /*fun renameFolder(from: String, to: String, source: Long) {
val sourceDir = rootDir.files[source] ?: return val sourceDir = rootDir.files[source] ?: return
val list = sourceDir.files.toMutableMap() val list = sourceDir.files.toMutableMap()
val mangaFiles = sourceDir.files[DiskUtil.buildValidFilename(from)] ?: return val mangaFiles = sourceDir.files[DiskUtil.buildValidFilename(from)] ?: return
@ -242,7 +218,7 @@ class DownloadCache(
list.remove(DiskUtil.buildValidFilename(from)) list.remove(DiskUtil.buildValidFilename(from))
list[to] = newDir list[to] = newDir
sourceDir.files = list sourceDir.files = list
} }*/
/** /**
@ -252,11 +228,7 @@ class DownloadCache(
*/ */
@Synchronized @Synchronized
fun removeManga(manga: Manga) { fun removeManga(manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return mangaFiles.remove(manga.id)
val mangaDirName = provider.getMangaDirName(manga)
if (mangaDirName in sourceDir.files) {
sourceDir.files -= mangaDirName
}
} }
/** /**
@ -269,13 +241,13 @@ class DownloadCache(
* Class to store the files under a source directory. * Class to store the files under a source directory.
*/ */
private class SourceDirectory(val dir: UniFile, private class SourceDirectory(val dir: UniFile,
var files: Map<String, MangaDirectory> = hashMapOf()) var files: Map<Long, MutableSet<String>> = hashMapOf())
/** /**
* Class to store the files under a manga directory. * Class to store the files under a manga directory.
*/ */
private class MangaDirectory(val dir: UniFile, private class MangaDirectory(val dir: UniFile,
var files: Set<String> = hashSetOf()) var files: MutableSet<String> = hashSetOf())
/** /**
* Returns a new map containing only the key entries of [transform] that are not null. * Returns a new map containing only the key entries of [transform] that are not null.

View File

@ -182,9 +182,9 @@ class DownloadManager(val context: Context) {
return cache.getDownloadCount(manga) return cache.getDownloadCount(manga)
} }
fun renameCache(from: String, to: String, source: Long) { /*fun renameCache(from: String, to: String, source: Long) {
cache.renameFolder(from, to, source) cache.renameFolder(from, to, source)
} }*/
/** /**
* Calls delete chapter, which deletes temp downloads * Calls delete chapter, which deletes temp downloads

View File

@ -136,8 +136,8 @@ class DownloadProvider(private val context: Context) {
val sourceDir = findSourceDir(source) val sourceDir = findSourceDir(source)
val mangaDir = sourceDir?.findFile(DiskUtil.buildValidFilename(from)) val mangaDir = sourceDir?.findFile(DiskUtil.buildValidFilename(from))
mangaDir?.renameTo(to) mangaDir?.renameTo(to)
val downloadManager:DownloadManager by injectLazy() // val downloadManager:DownloadManager by injectLazy()
downloadManager.renameCache(from, to, sourceId) // downloadManager.renameCache(from, to, sourceId)
} }
/** /**

View File

@ -558,6 +558,9 @@ open class BrowseCatalogueController(bundle: Bundle) :
presenter.moveMangaToCategory(manga, null) presenter.moveMangaToCategory(manga, null)
else -> { else -> {
val ids = presenter.getMangaCategoryIds(manga) val ids = presenter.getMangaCategoryIds(manga)
if (ids.isNullOrEmpty()) {
presenter.moveMangaToCategory(manga, null)
}
val preselected = ids.mapNotNull { id -> val preselected = ids.mapNotNull { id ->
categories.indexOfFirst { it.id == id }.takeIf { it != -1 } categories.indexOfFirst { it.id == id }.takeIf { it != -1 }
}.toTypedArray() }.toTypedArray()