diff --git a/CHANGELOG.md b/CHANGELOG.md index b41d8ae79..5db56d8fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,8 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co - Fix content under source browse screen top appbar is interactable ([@AntsyLich](https://github.com/AntsyLich)) ([#2026](https://github.com/mihonapp/mihon/pull/2026)) - Fix crash when trying use source sort filter without a pre-selection ([@AntsyLich](https://github.com/AntsyLich)) ([#2036](https://github.com/mihonapp/mihon/pull/2036)) - Fix empty layout not appearing in browse source screen in some cases ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#2043](https://github.com/mihonapp/mihon/pull/2043)) -- Fix Pill not following the local text style ([@AntsyLich](https://github.com/AntsyLich)) +- Fix Pill not following the local text style ([@AntsyLich](https://github.com/AntsyLich)) ([`f8cb506`](https://github.com/mihonapp/mihon/commit/f8cb506)) +- Fix downloader stopping after failing to create download directory of a manga ([@AntsyLich](https://github.com/AntsyLich)) ([#2068](https://github.com/mihonapp/mihon/pull/2068)) ### Removed - Remove Okhttp networking from WebView Screen ([@AwkwardPeak7](https://github.com/AwkwardPeak7)) ([#2020](https://github.com/mihonapp/mihon/pull/2020)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 9b651522b..6897f502a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -329,7 +329,10 @@ class DownloadManager( var cleaned = 0 if (removeNonFavorite && !manga.favorite) { - val mangaFolder = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) + val mangaFolder = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source).getOrElse { e -> + logcat(LogPriority.ERROR, e) { "Manga download folder doesn't exist." } + return 0 + } cleaned += 1 + mangaFolder.listFiles().orEmpty().size mangaFolder.delete() cache.removeManga(manga) @@ -350,7 +353,10 @@ class DownloadManager( } if (cache.getDownloadCount(manga) == 0) { - val mangaFolder = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) + val mangaFolder = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source).getOrElse { e -> + logcat(LogPriority.ERROR, e) { "Manga download folder doesn't exist." } + return cleaned + } if (!mangaFolder.listFiles().isNullOrEmpty()) { mangaFolder.delete() cache.removeManga(manga) @@ -419,7 +425,10 @@ class DownloadManager( */ suspend fun renameChapter(source: Source, manga: Manga, oldChapter: Chapter, newChapter: Chapter) { val oldNames = provider.getValidChapterDirNames(oldChapter.name, oldChapter.scanlator) - val mangaDir = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source) + val mangaDir = provider.getMangaDir(/* SY --> */ manga.ogTitle /* SY <-- */, source).getOrElse { e -> + logcat(LogPriority.ERROR, e) { "Manga download folder doesn't exist. Skipping renaming after source sync" } + return + } // Assume there's only 1 version of the chapter name formats present val oldDownload = oldNames.asSequence() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt index 9e72c7972..fb9f2cac0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt @@ -14,6 +14,7 @@ import tachiyomi.domain.storage.service.StorageManager import tachiyomi.i18n.MR import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.io.IOException /** * This class is used to provide the directories where the downloads should be saved. @@ -35,21 +36,36 @@ class DownloadProvider( * @param mangaTitle the title of the manga to query. * @param source the source of the manga. */ - internal fun getMangaDir(mangaTitle: String, source: Source): UniFile { - try { - return downloadsDir!! - .createDirectory(getSourceDirName(source))!! - .createDirectory(getMangaDirName(mangaTitle))!! - } catch (e: Throwable) { - logcat(LogPriority.ERROR, e) { "Invalid download directory" } - throw Exception( - context.stringResource( - MR.strings.invalid_location, - (downloadsDir?.displayablePath ?: "") + - "/${getSourceDirName(source)}/${getMangaDirName(mangaTitle)}", - ), + internal fun getMangaDir(mangaTitle: String, source: Source): Result { + val downloadsDir = downloadsDir + if (downloadsDir == null) { + logcat(LogPriority.ERROR) { "Failed to create download directory" } + return Result.failure( + IOException(context.stringResource(MR.strings.storage_failed_to_create_download_directory)), ) } + + val sourceDirName = getSourceDirName(source) + val sourceDir = downloadsDir.createDirectory(sourceDirName) + if (sourceDir == null) { + val displayablePath = downloadsDir.displayablePath + "/$sourceDirName" + logcat(LogPriority.ERROR) { "Failed to create source download directory: $displayablePath" } + return Result.failure( + IOException(context.stringResource(MR.strings.storage_failed_to_create_directory, displayablePath)), + ) + } + + val mangaDirName = getMangaDirName(mangaTitle) + val mangaDir = sourceDir.createDirectory(mangaDirName) + if (mangaDir == null) { + val displayablePath = sourceDir.displayablePath + "/$mangaDirName" + logcat(LogPriority.ERROR) { "Failed to create manga download directory: $displayablePath" } + return Result.failure( + IOException(context.stringResource(MR.strings.storage_failed_to_create_directory, displayablePath)), + ) + } + + return Result.success(mangaDir) } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index 4d4c261f1..62d8afc39 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -327,13 +327,9 @@ class Downloader( * @param download the chapter to be downloaded. */ private suspend fun downloadChapter(download: Download) { - val mangaDir: UniFile - try { - mangaDir = provider.getMangaDir(/* SY --> */ download.manga.ogTitle /* SY <-- */, download.source) - } catch (error: Exception) { - logcat(LogPriority.ERROR, error) + val mangaDir = provider.getMangaDir(/* SY --> */ download.manga.ogTitle /* SY <-- */, download.source).getOrElse { e -> download.status = Download.State.ERROR - notifier.onError(error.message, download.chapter.name, download.manga.title, download.manga.id) + notifier.onError(e.message, download.chapter.name, download.manga.title, download.manga.id) return } diff --git a/i18n/src/commonMain/moko-resources/base/strings.xml b/i18n/src/commonMain/moko-resources/base/strings.xml index cc283f176..616e4d74d 100644 --- a/i18n/src/commonMain/moko-resources/base/strings.xml +++ b/i18n/src/commonMain/moko-resources/base/strings.xml @@ -500,6 +500,8 @@ Excluded categories No storage location set Invalid location: %s + Failed to create download directory + Failed to create directory: %s Disabled Last read chapter Second to last read chapter