From 74826bc51bd94c1a57b4644ef895c3669ba29e99 Mon Sep 17 00:00:00 2001 From: Jays2Kings Date: Wed, 7 Apr 2021 01:41:05 -0400 Subject: [PATCH] Add Reader Page Preload option Based on jobobby04@68bfba4 Closes #544 Co-Authored-By: jobobby04 <17078382+jobobby04@users.noreply.github.com> --- .../tachiyomi/data/cache/ChapterCache.kt | 42 +++++++++++++++---- .../data/preference/PreferenceKeys.kt | 2 + .../data/preference/PreferencesHelper.kt | 2 + .../ui/reader/loader/HttpPageLoader.kt | 16 ++++++- .../ui/setting/SettingsReaderController.kt | 8 ++++ app/src/main/res/values/strings.xml | 7 ++++ 6 files changed, 69 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt index 217ef14479..11a7bffab6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt @@ -6,9 +6,15 @@ import com.github.salomonbrys.kotson.fromJson import com.google.gson.Gson import com.jakewharton.disklrucache.DiskLruCache import eu.kanade.tachiyomi.data.database.models.Chapter +import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.saveTo +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import okhttp3.Response import okio.buffer import okio.sink @@ -16,6 +22,8 @@ import rx.Observable import uy.kohesive.injekt.injectLazy import java.io.File import java.io.IOException +import kotlin.math.pow +import kotlin.math.roundToLong /** * Class used to create chapter cache @@ -39,19 +47,18 @@ class ChapterCache(private val context: Context) { const val PARAMETER_VALUE_COUNT = 1 /** The maximum number of bytes this cache should use to store. */ - const val PARAMETER_CACHE_SIZE = 75L * 1024 * 1024 + const val PARAMETER_CACHE_SIZE = 50L * 1024 * 1024 } /** Google Json class used for parsing JSON files. */ private val gson: Gson by injectLazy() + private val preferences: PreferencesHelper by injectLazy() + + private val scope = CoroutineScope(Job() + Dispatchers.IO) + /** Cache class used for cache management. */ - private val diskCache = DiskLruCache.open( - File(context.cacheDir, PARAMETER_CACHE_DIRECTORY), - PARAMETER_APP_VERSION, - PARAMETER_VALUE_COUNT, - PARAMETER_CACHE_SIZE - ) + private var diskCache = setupDiskCache(preferences.preloadSize().get()) /** * Returns directory of cache. @@ -71,6 +78,27 @@ class ChapterCache(private val context: Context) { val readableSize: String get() = Formatter.formatFileSize(context, realSize) + init { + preferences.preloadSize().asFlow() + .onEach { + // Save old cache for destruction later + val oldCache = diskCache + diskCache = setupDiskCache(it) + oldCache.close() + } + .launchIn(scope) + } + + private fun setupDiskCache(cacheSize: Int): DiskLruCache { + return DiskLruCache.open( + File(context.cacheDir, PARAMETER_CACHE_DIRECTORY), + PARAMETER_APP_VERSION, + PARAMETER_VALUE_COUNT, + // 4 pages = 115MB, 6 = ~150MB, 10 = ~200MB, 20 = ~300MB + (PARAMETER_CACHE_SIZE * cacheSize.toFloat().pow(0.6f)).roundToLong() + ) + } + /** * Remove file from cache. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index f5f6e3c822..127dd91056 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -70,6 +70,8 @@ object PreferenceKeys { const val showNavigationOverlayNewUser = "reader_navigation_overlay_new_user" const val showNavigationOverlayNewUserWebtoon = "reader_navigation_overlay_new_user_webtoon" + const val preloadSize = "preload_size" + const val webtoonSidePadding = "webtoon_side_padding" const val webtoonEnableZoomOut = "webtoon_enable_zoom_out" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 6280c9f1d3..da931dbe45 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -151,6 +151,8 @@ class PreferencesHelper(val context: Context) { fun showNavigationOverlayNewUserWebtoon() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUserWebtoon, true) + fun preloadSize() = flowPrefs.getInt(Keys.preloadSize, 6) + fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, false) fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt index 8d78cfeb64..d81f64b878 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt @@ -10,6 +10,12 @@ import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerPageHolder import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.system.ImageUtil +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach import rx.Completable import rx.Observable import rx.schedulers.Schedulers @@ -41,9 +47,16 @@ class HttpPageLoader( private val subscriptions = CompositeSubscription() private val preferences by injectLazy() - private val preloadSize = 4 + private var preloadSize = preferences.preloadSize().get() + private val scope = CoroutineScope(Job() + Dispatchers.IO) init { + // Adding flow since we can reach reader settings after this is created + preferences.preloadSize().asFlow() + .onEach { + preloadSize = it + } + .launchIn(scope) subscriptions += Observable.defer { Observable.just(queue.take().page) } .filter { it.status == Page.QUEUE } .concatMap { source.fetchImageFromCacheThenNet(it) } @@ -65,6 +78,7 @@ class HttpPageLoader( */ override fun recycle() { super.recycle() + scope.cancel() subscriptions.unsubscribe() queue.clear() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt index ea7fd5aa8f..31df2fe3fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt @@ -57,6 +57,14 @@ class SettingsReaderController : SettingsController() { defaultValue = false } } + intListPreference(activity) { + key = Keys.preloadSize + titleRes = R.string.page_preload_amount + entryValues = listOf(4, 6, 8, 10, 12, 14, 16, 20) + entries = entryValues.map { context.resources.getQuantityString(R.plurals.pages_plural, it, it) } + defaultValue = 6 + summaryRes = R.string.amount_of_pages_to_preload + } } preferenceCategory { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2875749ed7..0458fdbe5b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -330,6 +330,8 @@ Double tap animation speed Show page number 32-bit color + Page preload amount + The amount of pages to preload when reading. Higher values will result in a smoother reading experience, at the cost of higher cache and network usage. Reduces banding, but impacts performance Crop borders @@ -406,6 +408,11 @@ Page layout While using automatic page layout, you can still switch between layouts while reading without overriding this setting Automatic (based on orientation) + + %1$d page + %1$d pages + + About this %1$s