Download ahead (#7226)
This commit is contained in:
parent
2e81e1b7d8
commit
f207e87722
6 changed files with 107 additions and 11 deletions
|
@ -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 a new issue