DownloadProvider: Only provide necessary info and not whole chapter/manga class (#7411)

This commit is contained in:
AntsyLich 2022-06-30 19:20:55 +06:00 committed by GitHub
parent 388dc2f103
commit e1525a5125
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 83 additions and 61 deletions

View File

@ -96,7 +96,7 @@ class SyncChaptersWithSource(
toAdd.add(toAddChapter) toAdd.add(toAddChapter)
} else { } else {
if (shouldUpdateDbChapter.await(dbChapter, chapter)) { if (shouldUpdateDbChapter.await(dbChapter, chapter)) {
if (dbChapter.name != chapter.name && downloadManager.isChapterDownloaded(dbChapter.toDbChapter(), manga.toDbManga())) { if (dbChapter.name != chapter.name && downloadManager.isChapterDownloaded(dbChapter.name, dbChapter.scanlator, manga.title, manga.source)) {
downloadManager.renameChapter(source, manga.toDbManga(), dbChapter.toDbChapter(), chapter.toDbChapter()) downloadManager.renameChapter(source, manga.toDbManga(), dbChapter.toDbChapter(), chapter.toDbChapter())
} }
var toChangeChapter = dbChapter.copy( var toChangeChapter = dbChapter.copy(

View File

@ -65,23 +65,31 @@ class DownloadCache(
/** /**
* Returns true if the chapter is downloaded. * Returns true if the chapter is downloaded.
* *
* @param chapter the chapter to check. * @param chapterName the name of the chapter to query.
* @param manga the manga of the chapter. * @param chapterScanlator scanlator of the chapter to query
* @param mangaTitle the title of the manga to query.
* @param sourceId the id of the source of the chapter.
* @param skipCache whether to skip the directory cache and check in the filesystem. * @param skipCache whether to skip the directory cache and check in the filesystem.
*/ */
fun isChapterDownloaded(chapter: Chapter, manga: Manga, skipCache: Boolean): Boolean { fun isChapterDownloaded(
chapterName: String,
chapterScanlator: String?,
mangaTitle: String,
sourceId: Long,
skipCache: Boolean,
): Boolean {
if (skipCache) { if (skipCache) {
val source = sourceManager.getOrStub(manga.source) val source = sourceManager.getOrStub(sourceId)
return provider.findChapterDir(chapter, manga, source) != null return provider.findChapterDir(chapterName, chapterScanlator, mangaTitle, source) != null
} }
checkRenew() checkRenew()
val sourceDir = rootDir.files[manga.source] val sourceDir = rootDir.files[sourceId]
if (sourceDir != null) { if (sourceDir != null) {
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] val mangaDir = sourceDir.files[provider.getMangaDirName(mangaTitle)]
if (mangaDir != null) { if (mangaDir != null) {
return provider.getValidChapterDirNames(chapter).any { it in mangaDir.files } return provider.getValidChapterDirNames(chapterName, chapterScanlator).any { it in mangaDir.files }
} }
} }
return false return false
@ -97,7 +105,7 @@ class DownloadCache(
val sourceDir = rootDir.files[manga.source] val sourceDir = rootDir.files[manga.source]
if (sourceDir != null) { if (sourceDir != null) {
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] val mangaDir = sourceDir.files[provider.getMangaDirName(manga.title)]
if (mangaDir != null) { if (mangaDir != null) {
return mangaDir.files return mangaDir.files
.filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) } .filter { !it.endsWith(Downloader.TMP_DIR_SUFFIX) }
@ -174,7 +182,7 @@ class DownloadCache(
} }
// Retrieve the cached manga directory or cache a new one // Retrieve the cached manga directory or cache a new one
val mangaDirName = provider.getMangaDirName(manga) val mangaDirName = provider.getMangaDirName(manga.title)
var mangaDir = sourceDir.files[mangaDirName] var mangaDir = sourceDir.files[mangaDirName]
if (mangaDir == null) { if (mangaDir == null) {
mangaDir = MangaDirectory(mangaUniFile) mangaDir = MangaDirectory(mangaUniFile)
@ -194,8 +202,8 @@ class DownloadCache(
@Synchronized @Synchronized
fun removeChapter(chapter: Chapter, manga: Manga) { fun removeChapter(chapter: Chapter, manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return val sourceDir = rootDir.files[manga.source] ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return val mangaDir = sourceDir.files[provider.getMangaDirName(manga.title)] ?: return
provider.getValidChapterDirNames(chapter).forEach { provider.getValidChapterDirNames(chapter.name, chapter.scanlator).forEach {
if (it in mangaDir.files) { if (it in mangaDir.files) {
mangaDir.files -= it mangaDir.files -= it
} }
@ -211,9 +219,9 @@ 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 sourceDir = rootDir.files[manga.source] ?: return
val mangaDir = sourceDir.files[provider.getMangaDirName(manga)] ?: return val mangaDir = sourceDir.files[provider.getMangaDirName(manga.title)] ?: return
chapters.forEach { chapter -> chapters.forEach { chapter ->
provider.getValidChapterDirNames(chapter).forEach { provider.getValidChapterDirNames(chapter.name, chapter.scanlator).forEach {
if (it in mangaDir.files) { if (it in mangaDir.files) {
mangaDir.files -= it mangaDir.files -= it
} }
@ -229,7 +237,7 @@ class DownloadCache(
@Synchronized @Synchronized
fun removeManga(manga: Manga) { fun removeManga(manga: Manga) {
val sourceDir = rootDir.files[manga.source] ?: return val sourceDir = rootDir.files[manga.source] ?: return
val mangaDirName = provider.getMangaDirName(manga) val mangaDirName = provider.getMangaDirName(manga.title)
if (mangaDirName in sourceDir.files) { if (mangaDirName in sourceDir.files) {
sourceDir.files -= mangaDirName sourceDir.files -= mangaDirName
} }

View File

@ -163,7 +163,7 @@ class DownloadManager(
* @return an observable containing the list of pages from the chapter. * @return an observable containing the list of pages from the chapter.
*/ */
fun buildPageList(source: Source, manga: Manga, chapter: Chapter): Observable<List<Page>> { fun buildPageList(source: Source, manga: Manga, chapter: Chapter): Observable<List<Page>> {
return buildPageList(provider.findChapterDir(chapter, manga, source)) return buildPageList(provider.findChapterDir(chapter.name, chapter.scanlator, manga.title, source))
} }
/** /**
@ -191,12 +191,20 @@ class DownloadManager(
/** /**
* Returns true if the chapter is downloaded. * Returns true if the chapter is downloaded.
* *
* @param chapter the chapter to check. * @param chapterName the name of the chapter to query.
* @param manga the manga of the chapter. * @param chapterScanlator scanlator of the chapter to query
* @param mangaTitle the title of the manga to query.
* @param sourceId the id of the source of the chapter.
* @param skipCache whether to skip the directory cache and check in the filesystem. * @param skipCache whether to skip the directory cache and check in the filesystem.
*/ */
fun isChapterDownloaded(chapter: Chapter, manga: Manga, skipCache: Boolean = false): Boolean { fun isChapterDownloaded(
return cache.isChapterDownloaded(chapter, manga, skipCache) chapterName: String,
chapterScanlator: String?,
mangaTitle: String,
sourceId: Long,
skipCache: Boolean = false,
): Boolean {
return cache.isChapterDownloaded(chapterName, chapterScanlator, mangaTitle, sourceId, skipCache)
} }
/** /**
@ -292,7 +300,7 @@ class DownloadManager(
fun deleteManga(manga: Manga, source: Source) { fun deleteManga(manga: Manga, source: Source) {
launchIO { launchIO {
downloader.queue.remove(manga) downloader.queue.remove(manga)
provider.findMangaDir(manga, source)?.delete() provider.findMangaDir(manga.title, source)?.delete()
cache.removeManga(manga) cache.removeManga(manga)
} }
} }
@ -327,15 +335,15 @@ class DownloadManager(
* @param newChapter the target chapter with the new name. * @param newChapter the target chapter with the new name.
*/ */
fun renameChapter(source: Source, manga: Manga, oldChapter: Chapter, newChapter: Chapter) { fun renameChapter(source: Source, manga: Manga, oldChapter: Chapter, newChapter: Chapter) {
val oldNames = provider.getValidChapterDirNames(oldChapter) val oldNames = provider.getValidChapterDirNames(oldChapter.name, oldChapter.scanlator)
val mangaDir = provider.getMangaDir(manga, source) val mangaDir = provider.getMangaDir(manga.title, source)
// Assume there's only 1 version of the chapter name formats present // Assume there's only 1 version of the chapter name formats present
val oldDownload = oldNames.asSequence() val oldDownload = oldNames.asSequence()
.mapNotNull { mangaDir.findFile(it) } .mapNotNull { mangaDir.findFile(it) }
.firstOrNull() ?: return .firstOrNull() ?: return
var newName = provider.getChapterDirName(newChapter) var newName = provider.getChapterDirName(newChapter.name, newChapter.scanlator)
if (oldDownload.isFile && oldDownload.name?.endsWith(".cbz") == true) { if (oldDownload.isFile && oldDownload.name?.endsWith(".cbz") == true) {
newName += ".cbz" newName += ".cbz"
} }

View File

@ -46,14 +46,14 @@ class DownloadProvider(private val context: Context) {
/** /**
* Returns the download directory for a manga. For internal use only. * Returns the download directory for a manga. For internal use only.
* *
* @param manga the manga to query. * @param mangaTitle the title of the manga to query.
* @param source the source of the manga. * @param source the source of the manga.
*/ */
internal fun getMangaDir(manga: Manga, source: Source): UniFile { internal fun getMangaDir(mangaTitle: String, source: Source): UniFile {
try { try {
return downloadsDir return downloadsDir
.createDirectory(getSourceDirName(source)) .createDirectory(getSourceDirName(source))
.createDirectory(getMangaDirName(manga)) .createDirectory(getMangaDirName(mangaTitle))
} catch (e: Throwable) { } catch (e: Throwable) {
logcat(LogPriority.ERROR, e) { "Invalid download directory" } logcat(LogPriority.ERROR, e) { "Invalid download directory" }
throw Exception(context.getString(R.string.invalid_download_dir)) throw Exception(context.getString(R.string.invalid_download_dir))
@ -72,24 +72,25 @@ class DownloadProvider(private val context: Context) {
/** /**
* Returns the download directory for a manga if it exists. * Returns the download directory for a manga if it exists.
* *
* @param manga the manga to query. * @param mangaTitle the title of the manga to query.
* @param source the source of the manga. * @param source the source of the manga.
*/ */
fun findMangaDir(manga: Manga, source: Source): UniFile? { fun findMangaDir(mangaTitle: String, source: Source): UniFile? {
val sourceDir = findSourceDir(source) val sourceDir = findSourceDir(source)
return sourceDir?.findFile(getMangaDirName(manga), true) return sourceDir?.findFile(getMangaDirName(mangaTitle), true)
} }
/** /**
* Returns the download directory for a chapter if it exists. * Returns the download directory for a chapter if it exists.
* *
* @param chapter the chapter to query. * @param chapterName the name of the chapter to query.
* @param manga the manga of the chapter. * @param chapterScanlator scanlator of the chapter to query
* @param mangaTitle the title of the manga to query.
* @param source the source of the chapter. * @param source the source of the chapter.
*/ */
fun findChapterDir(chapter: Chapter, manga: Manga, source: Source): UniFile? { fun findChapterDir(chapterName: String, chapterScanlator: String?, mangaTitle: String, source: Source): UniFile? {
val mangaDir = findMangaDir(manga, source) val mangaDir = findMangaDir(mangaTitle, source)
return getValidChapterDirNames(chapter).asSequence() return getValidChapterDirNames(chapterName, chapterScanlator).asSequence()
.mapNotNull { mangaDir?.findFile(it, true) } .mapNotNull { mangaDir?.findFile(it, true) }
.firstOrNull() .firstOrNull()
} }
@ -102,9 +103,9 @@ class DownloadProvider(private val context: Context) {
* @param source the source of the chapter. * @param source the source of the chapter.
*/ */
fun findChapterDirs(chapters: List<Chapter>, manga: Manga, source: Source): List<UniFile> { fun findChapterDirs(chapters: List<Chapter>, manga: Manga, source: Source): List<UniFile> {
val mangaDir = findMangaDir(manga, source) ?: return emptyList() val mangaDir = findMangaDir(manga.title, source) ?: return emptyList()
return chapters.mapNotNull { chapter -> return chapters.mapNotNull { chapter ->
getValidChapterDirNames(chapter).asSequence() getValidChapterDirNames(chapter.name, chapter.scanlator).asSequence()
.mapNotNull { mangaDir.findFile(it) } .mapNotNull { mangaDir.findFile(it) }
.firstOrNull() .firstOrNull()
} }
@ -122,22 +123,23 @@ class DownloadProvider(private val context: Context) {
/** /**
* Returns the download directory name for a manga. * Returns the download directory name for a manga.
* *
* @param manga the manga to query. * @param mangaTitle the title of the manga to query.
*/ */
fun getMangaDirName(manga: Manga): String { fun getMangaDirName(mangaTitle: String): String {
return DiskUtil.buildValidFilename(manga.title) return DiskUtil.buildValidFilename(mangaTitle)
} }
/** /**
* Returns the chapter directory name for a chapter. * Returns the chapter directory name for a chapter.
* *
* @param chapter the chapter to query. * @param chapterName the name of the chapter to query.
* @param chapterScanlator scanlator of the chapter to query
*/ */
fun getChapterDirName(chapter: Chapter): String { fun getChapterDirName(chapterName: String, chapterScanlator: String?): String {
return DiskUtil.buildValidFilename( return DiskUtil.buildValidFilename(
when { when {
chapter.scanlator != null -> "${chapter.scanlator}_${chapter.name}" chapterScanlator != null -> "${chapterScanlator}_$chapterName"
else -> chapter.name else -> chapterName
}, },
) )
} }
@ -145,19 +147,20 @@ class DownloadProvider(private val context: Context) {
/** /**
* Returns valid downloaded chapter directory names. * Returns valid downloaded chapter directory names.
* *
* @param chapter the chapter to query. * @param chapterName the name of the chapter to query.
* @param chapterScanlator scanlator of the chapter to query
*/ */
fun getValidChapterDirNames(chapter: Chapter): List<String> { fun getValidChapterDirNames(chapterName: String, chapterScanlator: String?): List<String> {
val chapterName = getChapterDirName(chapter) val chapterDirName = getChapterDirName(chapterName, chapterScanlator)
return listOf( return listOf(
// Folder of images // Folder of images
chapterName, chapterDirName,
// Archived chapters // Archived chapters
"$chapterName.cbz", "$chapterDirName.cbz",
// 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(chapterName),
) )
} }
} }

View File

@ -252,7 +252,7 @@ class Downloader(
val chaptersWithoutDir = async { val chaptersWithoutDir = async {
chapters chapters
// Filter out those already downloaded. // Filter out those already downloaded.
.filter { provider.findChapterDir(it, manga, source) == null } .filter { provider.findChapterDir(it.name, it.scanlator, manga.title, source) == null }
// Add chapters to queue from the start. // Add chapters to queue from the start.
.sortedByDescending { it.source_order } .sortedByDescending { it.source_order }
} }
@ -303,7 +303,7 @@ class Downloader(
* @param download the chapter to be downloaded. * @param download the chapter to be downloaded.
*/ */
private fun downloadChapter(download: Download): Observable<Download> = Observable.defer { private fun downloadChapter(download: Download): Observable<Download> = Observable.defer {
val mangaDir = provider.getMangaDir(download.manga, download.source) val mangaDir = provider.getMangaDir(download.manga.title, download.source)
val availSpace = DiskUtil.getAvailableStorageSpace(mangaDir) val availSpace = DiskUtil.getAvailableStorageSpace(mangaDir)
if (availSpace != -1L && availSpace < MIN_DISK_SPACE) { if (availSpace != -1L && availSpace < MIN_DISK_SPACE) {
@ -312,7 +312,7 @@ class Downloader(
return@defer Observable.just(download) return@defer Observable.just(download)
} }
val chapterDirname = provider.getChapterDirName(download.chapter) val chapterDirname = provider.getChapterDirName(download.chapter.name, download.chapter.scanlator)
val tmpDir = mangaDir.createDirectory(chapterDirname + TMP_DIR_SUFFIX) val tmpDir = mangaDir.createDirectory(chapterDirname + TMP_DIR_SUFFIX)
val pageListObservable = if (download.pages == null) { val pageListObservable = if (download.pages == null) {

View File

@ -435,7 +435,7 @@ class MangaPresenter(
private fun List<DomainChapter>.toChapterItems(manga: DomainManga): List<ChapterItem> { private fun List<DomainChapter>.toChapterItems(manga: DomainManga): List<ChapterItem> {
return map { chapter -> return map { chapter ->
val activeDownload = downloadManager.queue.find { chapter.id == it.chapter.id } val activeDownload = downloadManager.queue.find { chapter.id == it.chapter.id }
val downloaded = downloadManager.isChapterDownloaded(chapter.toDbChapter(), manga.toDbManga()) val downloaded = downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)
val downloadState = when { val downloadState = when {
activeDownload != null -> activeDownload.status activeDownload != null -> activeDownload.status
downloaded -> Download.State.DOWNLOADED downloaded -> Download.State.DOWNLOADED

View File

@ -131,8 +131,8 @@ class ReaderPresenter(
preferences.skipFiltered() -> { preferences.skipFiltered() -> {
(manga.readFilter == Manga.CHAPTER_SHOW_READ && !it.read) || (manga.readFilter == Manga.CHAPTER_SHOW_READ && !it.read) ||
(manga.readFilter == Manga.CHAPTER_SHOW_UNREAD && it.read) || (manga.readFilter == Manga.CHAPTER_SHOW_UNREAD && it.read) ||
(manga.downloadedFilter == Manga.CHAPTER_SHOW_DOWNLOADED && !downloadManager.isChapterDownloaded(it, manga)) || (manga.downloadedFilter == Manga.CHAPTER_SHOW_DOWNLOADED && !downloadManager.isChapterDownloaded(it.name, it.scanlator, manga.title, manga.source)) ||
(manga.downloadedFilter == Manga.CHAPTER_SHOW_NOT_DOWNLOADED && downloadManager.isChapterDownloaded(it, manga)) || (manga.downloadedFilter == Manga.CHAPTER_SHOW_NOT_DOWNLOADED && downloadManager.isChapterDownloaded(it.name, it.scanlator, manga.title, manga.source)) ||
(manga.bookmarkedFilter == Manga.CHAPTER_SHOW_BOOKMARKED && !it.bookmark) || (manga.bookmarkedFilter == Manga.CHAPTER_SHOW_BOOKMARKED && !it.bookmark) ||
(manga.bookmarkedFilter == Manga.CHAPTER_SHOW_NOT_BOOKMARKED && it.bookmark) (manga.bookmarkedFilter == Manga.CHAPTER_SHOW_NOT_BOOKMARKED && it.bookmark)
} }
@ -362,7 +362,8 @@ class ReaderPresenter(
private fun preload(chapter: ReaderChapter) { private fun preload(chapter: ReaderChapter) {
if (chapter.pageLoader is HttpPageLoader) { if (chapter.pageLoader is HttpPageLoader) {
val manga = manga ?: return val manga = manga ?: return
val isDownloaded = downloadManager.isChapterDownloaded(chapter.chapter, manga) val dbChapter = chapter.chapter
val isDownloaded = downloadManager.isChapterDownloaded(dbChapter.name, dbChapter.scanlator, manga.title, manga.source)
if (isDownloaded) { if (isDownloaded) {
chapter.state = ReaderChapter.State.Wait chapter.state = ReaderChapter.State.Wait
} }

View File

@ -76,7 +76,8 @@ class ChapterLoader(
* Returns the page loader to use for this [chapter]. * Returns the page loader to use for this [chapter].
*/ */
private fun getPageLoader(chapter: ReaderChapter): PageLoader { private fun getPageLoader(chapter: ReaderChapter): PageLoader {
val isDownloaded = downloadManager.isChapterDownloaded(chapter.chapter, manga, true) val dbChapter = chapter.chapter
val isDownloaded = downloadManager.isChapterDownloaded(dbChapter.name, dbChapter.scanlator, manga.title, manga.source, skipCache = true)
return when { return when {
isDownloaded -> DownloadPageLoader(chapter, manga, source, downloadManager) isDownloaded -> DownloadPageLoader(chapter, manga, source, downloadManager)
source is HttpSource -> HttpPageLoader(chapter, source) source is HttpSource -> HttpPageLoader(chapter, source)

View File

@ -30,7 +30,8 @@ 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) val dbChapter = chapter.chapter
val chapterPath = downloadManager.provider.findChapterDir(dbChapter.name, dbChapter.scanlator, manga.title, source)
return if (chapterPath?.isFile == true) { return if (chapterPath?.isFile == true) {
getPagesFromArchive(chapterPath) getPagesFromArchive(chapterPath)
} else { } else {

View File

@ -121,7 +121,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
val manga = item.manga val manga = item.manga
val chapter = item.chapter val chapter = item.chapter
if (downloadManager.isChapterDownloaded(chapter, manga)) { if (downloadManager.isChapterDownloaded(chapter.name, chapter.scanlator, manga.title, manga.source)) {
item.status = Download.State.DOWNLOADED item.status = Download.State.DOWNLOADED
} }
} }