Add ability to hide transition page between chapters

This commit is contained in:
NerdNumber9 2019-04-12 22:59:49 -04:00
parent 8ccc3c8b0c
commit 8e9087226f
9 changed files with 113 additions and 25 deletions

View File

@ -178,4 +178,6 @@ object PreferenceKeys {
const val eh_autoSolveCaptchas = "eh_autosolve_captchas"
const val eh_delegateSources = "eh_delegate_sources"
const val eh_showTransitionPages = "eh_show_transition_pages"
}

View File

@ -251,4 +251,6 @@ class PreferencesHelper(val context: Context) {
fun eh_lastVersionCode() = rxPrefs.getInteger("eh_last_version_code", 0)
fun eh_savedSearches() = rxPrefs.getStringSet("eh_saved_searches", emptySet())
fun eh_showTransitionPages() = rxPrefs.getBoolean(Keys.eh_showTransitionPages, true)
}

View File

@ -90,6 +90,9 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
private var autoscrollSubscription: Subscription? = null
private val sourceManager: SourceManager by injectLazy()
private val prefs: PreferencesHelper by injectLazy()
val showTransitionPages by lazy { prefs.eh_showTransitionPages().getOrDefault() }
// <-- EH
/**
@ -167,9 +170,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() {
expand_eh_button.setImageResource(R.drawable.ic_keyboard_arrow_down_white_32dp)
}
}
// <-- EH
// --> EH
private fun setupAutoscroll(interval: Float) {
exhSubscriptions.remove(autoscrollSubscription)
autoscrollSubscription = null

View File

@ -32,7 +32,7 @@ import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.File
import java.util.Date
import java.util.*
import java.util.concurrent.TimeUnit
/**
@ -77,6 +77,10 @@ class ReaderPresenter(
*/
private val isLoadingAdjacentChapterRelay = BehaviorRelay.create<Boolean>()
// EXH -->
private var loadKey: String? = null
// EXH <--
/**
* 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.
@ -211,7 +215,8 @@ class ReaderPresenter(
*/
private fun getLoadObservable(
loader: ChapterLoader,
chapter: ReaderChapter
chapter: ReaderChapter,
requiredLoadKey: String? = null
): Observable<ViewerChapters> {
return loader.loadChapter(chapter)
.andThen(Observable.fromCallable {
@ -223,13 +228,20 @@ class ReaderPresenter(
})
.observeOn(AndroidSchedulers.mainThread())
.doOnNext { newChapters ->
val oldChapters = viewerChaptersRelay.value
// Add new references first to avoid unnecessary recycling
newChapters.ref()
// Ensure that we haven't made another load request in the meantime
if(requiredLoadKey == null || requiredLoadKey == loadKey) {
val oldChapters = viewerChaptersRelay.value
oldChapters?.unref()
viewerChaptersRelay.call(newChapters)
} else {
// Another load request has been made, our new chapters are useless :(
newChapters.unref()
}
}
}
@ -242,8 +254,11 @@ class ReaderPresenter(
Timber.d("Loading ${chapter.chapter.url}")
val newLoadKey = UUID.randomUUID().toString()
loadKey = newLoadKey
activeChapterSubscription?.unsubscribe()
activeChapterSubscription = getLoadObservable(loader, chapter)
activeChapterSubscription = getLoadObservable(loader, chapter, newLoadKey)
.toCompletable()
.onErrorComplete()
.subscribe()

View File

@ -37,18 +37,18 @@ class ChapterLoader(
Timber.d("Loading pages for ${chapter.chapter.name}")
val loader = getPageLoader(it)
chapter.pageLoader = loader
loader.getPages().take(1).doOnNext { pages ->
pages.forEach { it.chapter = chapter }
}
}.map { pages -> loader to pages }
}
.observeOn(AndroidSchedulers.mainThread())
.doOnNext { pages ->
.doOnNext { (loader, pages) ->
if (pages.isEmpty()) {
throw Exception("Page list is empty")
}
chapter.pageLoader = loader // Assign here to fix race with unref
chapter.state = ReaderChapter.State.Loaded(pages)
// If the chapter is partially read, set the starting page to the last the user read

View File

@ -9,6 +9,7 @@ import android.view.ViewGroup.LayoutParams
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
@ -41,6 +42,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
*/
/* [EXH] private */ var currentPage: Any? = null
// EXH -->
private var nextChapter: ReaderChapter? = null
private var prevChapter: ReaderChapter? = null
// EXH <--
/**
* Viewer chapters to set when the pager enters idle mode. Otherwise, if the view was settling
* or dragging, there'd be a noticeable and annoying jump.
@ -137,13 +143,21 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
Timber.d("onPageSelected: ${page.number}/${pages.size}")
activity.onPageSelected(page)
if (page === pages.last()) {
if (page === pages.last() || page === pages.getOrNull(pages.lastIndex - 1)) {
Timber.d("Request preload next chapter because we're at the last page")
val transition = adapter.items.getOrNull(position + 1) as? ChapterTransition.Next
if (transition?.to != null) {
activity.requestPreloadChapter(transition.to)
// EXH -->
nextChapter?.let {
activity.requestPreloadChapter(it)
}
// EXH <--
}
// EXH -->
if(page === pages.first() || page === pages.getOrNull(1)) {
prevChapter?.let {
activity.requestPreloadChapter(it)
}
}
// EXH <--
}
/**
@ -167,6 +181,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* it sets the chapters immediately, otherwise they are saved and set when it becomes idle.
*/
override fun setChapters(chapters: ViewerChapters) {
// EXH -->
nextChapter = chapters.nextChapter
prevChapter = chapters.prevChapter
// EXH <--
if (isIdle) {
setChaptersInternal(chapters)
} else {
@ -187,6 +206,12 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
val pages = chapters.currChapter.pages ?: return
moveToPage(pages[chapters.currChapter.requestedPage])
pager.visibility = View.VISIBLE
} else {
// Trigger page change
val page = adapter.items.getOrNull(pager.currentItem)
if(page is ReaderPage) {
onPageSelected(page, pager.currentItem)
}
}
}
@ -197,7 +222,14 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
Timber.d("moveToPage")
val position = adapter.items.indexOf(page)
if (position != -1) {
// EXH -->
if(position == pager.currentItem) {
// Invoke anyways to update seekbar
onPageSelected(page, position)
} else {
pager.setCurrentItem(position, true)
}
// EXH <--
} else {
Timber.d("Page $page not found in adapter")
}

View File

@ -37,7 +37,13 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
newItems.addAll(prevPages.takeLast(2))
}
}
// EXH -->
if(viewer.activity.showTransitionPages) {
// EXH <--
newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter))
// EXH -->
}
// EXH <--
// Add current chapter.
val currPages = chapters.currChapter.pages
@ -46,7 +52,13 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
}
// Add next chapter transition and pages.
// EXH -->
if(viewer.activity.showTransitionPages) {
// EXH <--
newItems.add(ChapterTransition.Next(chapters.currChapter, chapters.nextChapter))
// EXH -->
}
// EXH <--
if (chapters.nextChapter != null) {
// Add at most two pages, because this chapter will be selected before the user can
// swap more pages.

View File

@ -47,21 +47,22 @@ class WebtoonTransitionHolder(
gravity = Gravity.CENTER
}
private val layoutPaddingVertical = 48.dpToPx
private val layoutPaddingHorizontal = 32.dpToPx
init {
layout.layoutParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT)
layout.orientation = LinearLayout.VERTICAL
layout.gravity = Gravity.CENTER
val paddingVertical = 48.dpToPx
val paddingHorizontal = 32.dpToPx
layout.setPadding(paddingHorizontal, paddingVertical, paddingHorizontal, paddingVertical)
val childMargins = 16.dpToPx
val childParams = LinearLayout.LayoutParams(MATCH_PARENT, WRAP_CONTENT).apply {
setMargins(0, childMargins, 0, childMargins)
}
if(viewer.activity.showTransitionPages) {
layout.addView(textView, childParams)
}
layout.addView(pagesContainer, childParams)
}
@ -88,6 +89,15 @@ class WebtoonTransitionHolder(
private fun bindNextChapterTransition(transition: ChapterTransition.Next) {
val nextChapter = transition.to
if(viewer.activity.showTransitionPages) {
layout.setPadding(
layoutPaddingHorizontal,
layoutPaddingVertical,
layoutPaddingHorizontal,
layoutPaddingVertical
)
}
textView.text = if (nextChapter != null) {
SpannableStringBuilder().apply {
append(context.getString(R.string.transition_finished))
@ -113,6 +123,13 @@ class WebtoonTransitionHolder(
private fun bindPrevChapterTransition(transition: ChapterTransition.Prev) {
val prevChapter = transition.to
layout.setPadding(
layoutPaddingHorizontal,
layoutPaddingVertical,
layoutPaddingHorizontal,
layoutPaddingVertical
)
textView.text = if (prevChapter != null) {
SpannableStringBuilder().apply {
append(context.getString(R.string.transition_current))
@ -174,7 +191,9 @@ class WebtoonTransitionHolder(
setText(R.string.transition_pages_loading)
}
if(viewer.activity.showTransitionPages) {
pagesContainer.addView(progress)
}
pagesContainer.addView(textView)
}

View File

@ -148,6 +148,11 @@ class SettingsReaderController : SettingsController() {
title = "Preserve reading position on read manga"
defaultValue = false
}
switchPreference {
key = Keys.eh_showTransitionPages
title = "Show transition pages between chapters"
defaultValue = true
}
// EXH <--
preferenceCategory {
titleRes = R.string.pager_viewer