diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index 4868d8d6f5..67e78d03f0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -48,6 +48,8 @@ class DownloadCache( private val scope = CoroutineScope(Dispatchers.IO) + private val notifier by lazy { DownloadNotifier(context) } + /** * The interval after which this cache should be invalidated. 1 hour shouldn't cause major * issues, as the cache is only used for UI feedback. @@ -241,56 +243,62 @@ class DownloadCache( } renewalJob = scope.launchIO { - var sources = getSources() + try { + notifier.onCacheProgress() - // Try to wait until extensions and sources have loaded - withTimeout(30.seconds) { - while (!extensionManager.isInitialized) { - delay(2.seconds) - } + var sources = getSources() - while (sources.isEmpty()) { - delay(2.seconds) - sources = getSources() - } - } + // Try to wait until extensions and sources have loaded + withTimeout(30.seconds) { + while (!extensionManager.isInitialized) { + delay(2.seconds) + } - val sourceDirs = rootDownloadsDir.dir.listFiles().orEmpty() - .associate { it.name to SourceDirectory(it) } - .mapNotNullKeys { entry -> - sources.find { - provider.getSourceDirName(it).equals(entry.key, ignoreCase = true) - }?.id - } - - rootDownloadsDir.sourceDirs = sourceDirs - - sourceDirs.values - .map { sourceDir -> - async { - val mangaDirs = sourceDir.dir.listFiles().orEmpty() - .filterNot { it.name.isNullOrBlank() } - .associate { it.name!! to MangaDirectory(it) } - - sourceDir.mangaDirs = ConcurrentHashMap(mangaDirs) - - mangaDirs.values.forEach { mangaDir -> - val chapterDirs = mangaDir.dir.listFiles().orEmpty() - .mapNotNull { chapterDir -> - chapterDir.name - ?.replace(".cbz", "") - ?.takeUnless { it.endsWith(Downloader.TMP_DIR_SUFFIX) } - } - .toMutableSet() - - mangaDir.chapterDirs = chapterDirs - } + while (sources.isEmpty()) { + delay(2.seconds) + sources = getSources() } } - .awaitAll() - lastRenew = System.currentTimeMillis() - notifyChanges() + val sourceDirs = rootDownloadsDir.dir.listFiles().orEmpty() + .associate { it.name to SourceDirectory(it) } + .mapNotNullKeys { entry -> + sources.find { + provider.getSourceDirName(it).equals(entry.key, ignoreCase = true) + }?.id + } + + rootDownloadsDir.sourceDirs = sourceDirs + + sourceDirs.values + .map { sourceDir -> + async { + val mangaDirs = sourceDir.dir.listFiles().orEmpty() + .filterNot { it.name.isNullOrBlank() } + .associate { it.name!! to MangaDirectory(it) } + + sourceDir.mangaDirs = ConcurrentHashMap(mangaDirs) + + mangaDirs.values.forEach { mangaDir -> + val chapterDirs = mangaDir.dir.listFiles().orEmpty() + .mapNotNull { chapterDir -> + chapterDir.name + ?.replace(".cbz", "") + ?.takeUnless { it.endsWith(Downloader.TMP_DIR_SUFFIX) } + } + .toMutableSet() + + mangaDir.chapterDirs = chapterDirs + } + } + } + .awaitAll() + + lastRenew = System.currentTimeMillis() + notifyChanges() + } finally { + notifier.dismissCacheProgress() + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt index e7621aea37..be54abc30b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt @@ -45,6 +45,17 @@ internal class DownloadNotifier(private val context: Context) { } } + private val cacheNotificationBuilder by lazy { + context.notificationBuilder(Notifications.CHANNEL_DOWNLOADER_CACHE) { + setSmallIcon(R.drawable.ic_tachi) + setContentTitle(context.getString(R.string.download_notifier_cache_renewal)) + setProgress(100, 100, true) + setOngoing(true) + setAutoCancel(false) + setOnlyAlertOnce(true) + } + } + /** * Status of download. Used for correct notification icon. */ @@ -233,4 +244,14 @@ internal class DownloadNotifier(private val context: Context) { errorThrown = true isDownloading = false } + + fun onCacheProgress() { + with(cacheNotificationBuilder) { + show(Notifications.ID_DOWNLOAD_CACHE) + } + } + + fun dismissCacheProgress() { + context.notificationManager.cancel(Notifications.ID_DOWNLOAD_CACHE) + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index bccc31140d..d89df8dab6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -42,6 +42,8 @@ object Notifications { const val ID_DOWNLOAD_CHAPTER_COMPLETE = -203 const val CHANNEL_DOWNLOADER_ERROR = "downloader_error_channel" const val ID_DOWNLOAD_CHAPTER_ERROR = -202 + const val CHANNEL_DOWNLOADER_CACHE = "downloader_cache_renewal" + const val ID_DOWNLOAD_CACHE = -204 /** * Notification channel and ids used by the library updater. @@ -159,6 +161,11 @@ object Notifications { setGroup(GROUP_DOWNLOADER) setShowBadge(false) }, + buildNotificationChannel(CHANNEL_DOWNLOADER_CACHE, IMPORTANCE_LOW) { + setName(context.getString(R.string.channel_downloader_cache)) + setGroup(GROUP_DOWNLOADER) + setShowBadge(false) + }, buildNotificationChannel(CHANNEL_BACKUP_RESTORE_PROGRESS, IMPORTANCE_LOW) { setName(context.getString(R.string.channel_progress)) setGroup(GROUP_BACKUP_RESTORE) diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index 17ffdfc4f7..d85d7b1dbf 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -863,6 +863,7 @@ Page %d not found while splitting Couldn\'t find file path of page %d Couldn\'t split downloaded image + Indexing downloads Common @@ -873,6 +874,7 @@ Chapter updates App updates Extension updates + Download cache Crash logs