mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Download ahead (#7226)
This commit is contained in:
		| @@ -157,6 +157,20 @@ class DownloadManager( | ||||
|         downloader.queueChapters(manga, chapters, autoStart) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Tells the downloader to enqueue the given list of downloads at the start of the queue. | ||||
|      * | ||||
|      * @param downloads the list of downloads to enqueue. | ||||
|      */ | ||||
|     fun addDownloadsToStartOfQueue(downloads: List<Download>) { | ||||
|         val wasEmpty = queue.isEmpty() | ||||
|         queue.toMutableList().apply { | ||||
|             addAll(0, downloads) | ||||
|             reorderQueue(this) | ||||
|         } | ||||
|         if (wasEmpty) startDownloads() | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Builds the page list of a downloaded chapter. | ||||
|      * | ||||
|   | ||||
| @@ -275,11 +275,13 @@ class PreferencesHelper(val context: Context) { | ||||
|  | ||||
|     fun pinnedSources() = flowPrefs.getStringSet("pinned_catalogues", emptySet()) | ||||
|  | ||||
|     fun downloadNewChapter() = flowPrefs.getBoolean("download_new", false) | ||||
|     fun downloadNewChapters() = flowPrefs.getBoolean("download_new", false) | ||||
|  | ||||
|     fun downloadNewChapterCategories() = flowPrefs.getStringSet("download_new_categories", emptySet()) | ||||
|     fun downloadNewChapterCategoriesExclude() = flowPrefs.getStringSet("download_new_categories_exclude", emptySet()) | ||||
|  | ||||
|     fun autoDownloadWhileReading() = flowPrefs.getInt("auto_download_while_reading", 0) | ||||
|  | ||||
|     fun defaultCategory() = prefs.getInt(Keys.defaultCategory, -1) | ||||
|  | ||||
|     fun categorizedDisplaySettings() = flowPrefs.getBoolean("categorized_display", false) | ||||
|   | ||||
| @@ -19,8 +19,10 @@ import eu.kanade.domain.track.interactor.GetTracks | ||||
| import eu.kanade.domain.track.interactor.InsertTrack | ||||
| import eu.kanade.domain.track.model.toDbTrack | ||||
| import eu.kanade.tachiyomi.data.database.models.Manga | ||||
| import eu.kanade.tachiyomi.data.database.models.toDomainChapter | ||||
| import eu.kanade.tachiyomi.data.database.models.toDomainManga | ||||
| import eu.kanade.tachiyomi.data.download.DownloadManager | ||||
| import eu.kanade.tachiyomi.data.download.model.Download | ||||
| import eu.kanade.tachiyomi.data.preference.PreferencesHelper | ||||
| import eu.kanade.tachiyomi.data.saver.Image | ||||
| import eu.kanade.tachiyomi.data.saver.ImageSaver | ||||
| @@ -32,6 +34,7 @@ import eu.kanade.tachiyomi.source.SourceManager | ||||
| import eu.kanade.tachiyomi.source.model.Page | ||||
| import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter | ||||
| import eu.kanade.tachiyomi.ui.reader.loader.ChapterLoader | ||||
| import eu.kanade.tachiyomi.ui.reader.loader.DownloadPageLoader | ||||
| import eu.kanade.tachiyomi.ui.reader.loader.HttpPageLoader | ||||
| import eu.kanade.tachiyomi.ui.reader.model.InsertPage | ||||
| import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter | ||||
| @@ -63,6 +66,7 @@ import uy.kohesive.injekt.injectLazy | ||||
| import java.util.Date | ||||
| import java.util.concurrent.TimeUnit | ||||
| import eu.kanade.domain.manga.model.Manga as DomainManga | ||||
| import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter | ||||
|  | ||||
| /** | ||||
|  * Presenter used by the activity to perform background operations. | ||||
| @@ -119,6 +123,8 @@ class ReaderPresenter( | ||||
|  | ||||
|     private val imageSaver: ImageSaver by injectLazy() | ||||
|  | ||||
|     private var chapterDownload: Download? = null | ||||
|  | ||||
|     /** | ||||
|      * Chapter list for the active manga. It's retrieved lazily and should be accessed for the first | ||||
|      * time in a background thread to avoid blocking the UI. | ||||
| @@ -191,6 +197,9 @@ class ReaderPresenter( | ||||
|         if (currentChapters != null) { | ||||
|             currentChapters.unref() | ||||
|             saveReadingProgress(currentChapters.currChapter) | ||||
|             chapterDownload?.let { | ||||
|                 downloadManager.addDownloadsToStartOfQueue(listOf(it)) | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -318,6 +327,7 @@ class ReaderPresenter( | ||||
|                 newChapters.ref() | ||||
|                 oldChapters?.unref() | ||||
|  | ||||
|                 chapterDownload = deleteChapterFromDownloadQueue(newChapters.currChapter) | ||||
|                 viewerChaptersRelay.call(newChapters) | ||||
|             } | ||||
|     } | ||||
| @@ -416,7 +426,6 @@ class ReaderPresenter( | ||||
|             selectedChapter.chapter.read = true | ||||
|             updateTrackChapterRead(selectedChapter) | ||||
|             deleteChapterIfNeeded(selectedChapter) | ||||
|             deleteChapterFromDownloadQueue(currentChapters.currChapter) | ||||
|         } | ||||
|  | ||||
|         if (selectedChapter != currentChapters.currChapter) { | ||||
| @@ -425,15 +434,56 @@ class ReaderPresenter( | ||||
|             setReadStartTime() | ||||
|             loadNewChapter(selectedChapter) | ||||
|         } | ||||
|         val pages = page.chapter.pages ?: return | ||||
|         val inDownloadRange = page.number.toDouble() / pages.size > 0.2 | ||||
|         if (inDownloadRange) { | ||||
|             downloadNextChapters() | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun downloadNextChapters() { | ||||
|         val manga = manga ?: return | ||||
|         if (getCurrentChapter()?.pageLoader !is DownloadPageLoader) return | ||||
|         val nextChapter = viewerChaptersRelay.value?.nextChapter?.chapter ?: return | ||||
|         val chaptersNumberToDownload = preferences.autoDownloadWhileReading().get() | ||||
|         if (chaptersNumberToDownload == 0 || !manga.favorite) return | ||||
|         val isNextChapterDownloaded = | ||||
|             downloadManager.isChapterDownloaded(nextChapter.name, nextChapter.scanlator, manga.title, manga.source) | ||||
|         if (isNextChapterDownloaded) { | ||||
|             downloadAutoNextChapters(chaptersNumberToDownload, nextChapter.id) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun downloadAutoNextChapters(choice: Int, nextChapterId: Long?) { | ||||
|         val chaptersToDownload = getNextUnreadChaptersSorted(nextChapterId).take(choice - 1) | ||||
|         if (chaptersToDownload.isNotEmpty()) { | ||||
|             downloadChapters(chaptersToDownload) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     private fun getNextUnreadChaptersSorted(nextChapterId: Long?): List<DbChapter> { | ||||
|         return chapterList.map { it.chapter.toDomainChapter()!! } | ||||
|             .filter { !it.read || it.id == nextChapterId } | ||||
|             .sortedWith(getChapterSort(manga?.toDomainManga()!!, false)) | ||||
|             .map { it.toDbChapter() } | ||||
|             .takeLastWhile { it.id != nextChapterId } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Downloads the given list of chapters with the manager. | ||||
|      * @param chapters the list of chapters to download. | ||||
|      */ | ||||
|     private fun downloadChapters(chapters: List<DbChapter>) { | ||||
|         downloadManager.downloadChapters(manga?.toDomainManga()!!, chapters) | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Removes [currentChapter] from download queue | ||||
|      * if setting is enabled and [currentChapter] is queued for download | ||||
|      */ | ||||
|     private fun deleteChapterFromDownloadQueue(currentChapter: ReaderChapter) { | ||||
|         downloadManager.getChapterDownloadOrNull(currentChapter.chapter)?.let { download -> | ||||
|             downloadManager.deletePendingDownload(download) | ||||
|     private fun deleteChapterFromDownloadQueue(currentChapter: ReaderChapter): Download? { | ||||
|         return downloadManager.getChapterDownloadOrNull(currentChapter.chapter)?.apply { | ||||
|             downloadManager.deletePendingDownload(this) | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -448,6 +498,9 @@ class ReaderPresenter( | ||||
|         val removeAfterReadSlots = preferences.removeAfterReadSlots() | ||||
|         val chapterToDelete = chapterList.getOrNull(currentChapterPosition - removeAfterReadSlots) | ||||
|  | ||||
|         if (removeAfterReadSlots != 0 && chapterDownload != null) { | ||||
|             downloadManager.addDownloadsToStartOfQueue(listOf(chapterDownload!!)) | ||||
|         } | ||||
|         // Check if deleting option is enabled and chapter exists | ||||
|         if (removeAfterReadSlots != -1 && chapterToDelete != null) { | ||||
|             enqueueDeleteReadChapters(chapterToDelete) | ||||
|   | ||||
| @@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.ui.base.controller.DialogController | ||||
| import eu.kanade.tachiyomi.util.preference.bindTo | ||||
| import eu.kanade.tachiyomi.util.preference.defaultValue | ||||
| import eu.kanade.tachiyomi.util.preference.entriesRes | ||||
| import eu.kanade.tachiyomi.util.preference.infoPreference | ||||
| import eu.kanade.tachiyomi.util.preference.intListPreference | ||||
| import eu.kanade.tachiyomi.util.preference.multiSelectListPreference | ||||
| import eu.kanade.tachiyomi.util.preference.onClick | ||||
| @@ -129,10 +130,10 @@ class SettingsDownloadController : SettingsController() { | ||||
|         } | ||||
|  | ||||
|         preferenceCategory { | ||||
|             titleRes = R.string.pref_category_auto_download | ||||
|             titleRes = R.string.pref_download_new | ||||
|  | ||||
|             switchPreference { | ||||
|                 bindTo(preferences.downloadNewChapter()) | ||||
|                 bindTo(preferences.downloadNewChapters()) | ||||
|                 titleRes = R.string.pref_download_new | ||||
|             } | ||||
|             preference { | ||||
| @@ -142,7 +143,7 @@ class SettingsDownloadController : SettingsController() { | ||||
|                     DownloadCategoriesDialog().showDialog(router) | ||||
|                 } | ||||
|  | ||||
|                 visibleIf(preferences.downloadNewChapter()) { it } | ||||
|                 visibleIf(preferences.downloadNewChapters()) { it } | ||||
|  | ||||
|                 fun updateSummary() { | ||||
|                     val selectedCategories = preferences.downloadNewChapterCategories().get() | ||||
| @@ -178,6 +179,25 @@ class SettingsDownloadController : SettingsController() { | ||||
|                     .launchIn(viewScope) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         preferenceCategory { | ||||
|             titleRes = R.string.download_ahead | ||||
|  | ||||
|             intListPreference { | ||||
|                 bindTo(preferences.autoDownloadWhileReading()) | ||||
|                 titleRes = R.string.auto_download_while_reading | ||||
|                 entries = arrayOf( | ||||
|                     context.getString(R.string.disabled), | ||||
|                     context.resources.getQuantityString(R.plurals.next_unread_chapters, 2, 2), | ||||
|                     context.resources.getQuantityString(R.plurals.next_unread_chapters, 3, 3), | ||||
|                     context.resources.getQuantityString(R.plurals.next_unread_chapters, 5, 5), | ||||
|                     context.resources.getQuantityString(R.plurals.next_unread_chapters, 10, 10), | ||||
|                 ) | ||||
|                 entryValues = arrayOf("0", "2", "3", "5", "10") | ||||
|                 summary = "%s" | ||||
|             } | ||||
|             infoPreference(R.string.download_ahead_info) | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { | ||||
|   | ||||
| @@ -57,8 +57,8 @@ fun DomainManga.shouldDownloadNewChapters(dbCategories: List<Long>, preferences: | ||||
|     val categories = dbCategories.ifEmpty { listOf(0L) } | ||||
|  | ||||
|     // Boolean to determine if user wants to automatically download new chapters. | ||||
|     val downloadNewChapter = preferences.downloadNewChapter().get() | ||||
|     if (!downloadNewChapter) return false | ||||
|     val downloadNewChapters = preferences.downloadNewChapters().get() | ||||
|     if (!downloadNewChapters) return false | ||||
|  | ||||
|     val includedCategories = preferences.downloadNewChapterCategories().get().map { it.toLong() } | ||||
|     val excludedCategories = preferences.downloadNewChapterCategoriesExclude().get().map { it.toLong() } | ||||
|   | ||||
| @@ -417,11 +417,18 @@ | ||||
|     <string name="pref_category_auto_download">Auto-download</string> | ||||
|     <string name="pref_download_new">Download new chapters</string> | ||||
|     <string name="pref_download_new_categories_details">Manga in excluded categories will not be downloaded even if they are also in included categories.</string> | ||||
|     <string name="download_ahead">Download ahead</string> | ||||
|     <string name="auto_download_while_reading">Auto download while reading</string> | ||||
|     <plurals name="next_unread_chapters"> | ||||
|         <item quantity="one">Next unread chapter</item> | ||||
|         <item quantity="other">Next %d unread chapters</item> | ||||
|     </plurals> | ||||
|     <string name="download_ahead_info">Only works on entries in library and if the current chapter plus the next one are already downloaded</string> | ||||
|     <string name="save_chapter_as_cbz">Save as CBZ archive</string> | ||||
|     <string name="split_tall_images">Split tall images</string> | ||||
|     <string name="split_tall_images_summary">Improves reader performance</string> | ||||
|  | ||||
|       <!-- Tracking section --> | ||||
|     <!-- Tracking section --> | ||||
|     <string name="tracking_guide">Tracking guide</string> | ||||
|     <string name="pref_auto_update_manga_sync">Update progress after reading</string> | ||||
|     <string name="services">Services</string> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user