mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 06:11:50 +01:00
Splitting double pages (#961)
* Split double pages * various fixes for split double page
This commit is contained in:
parent
ff9f79f2fc
commit
60d4c30e9a
@ -74,6 +74,8 @@ object PreferenceKeys {
|
||||
|
||||
const val pageLayout = "page_layout"
|
||||
|
||||
const val automaticSplitsPage = "automatic_splits_page"
|
||||
|
||||
const val invertDoublePages = "invert_double_pages"
|
||||
|
||||
const val readerBottomButtons = "reader_bottom_buttons"
|
||||
|
@ -186,6 +186,8 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun pageLayout() = flowPrefs.getInt(Keys.pageLayout, PageLayout.AUTOMATIC.value)
|
||||
|
||||
fun automaticSplitsPage() = flowPrefs.getBoolean(Keys.automaticSplitsPage, false)
|
||||
|
||||
fun invertDoublePages() = flowPrefs.getBoolean(Keys.invertDoublePages, false)
|
||||
|
||||
fun readerBottomButtons() = flowPrefs.getStringSet(
|
||||
|
@ -29,6 +29,7 @@ import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.isInvisible
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.lifecycle.Lifecycle
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
@ -342,8 +343,11 @@ class ReaderActivity :
|
||||
binding.chaptersSheet.doublePage.setImageDrawable(
|
||||
ContextCompat.getDrawable(
|
||||
this,
|
||||
if (!isDoublePage) R.drawable.ic_single_page_24dp
|
||||
else R.drawable.ic_book_open_variant_24dp
|
||||
when {
|
||||
isDoublePage -> R.drawable.ic_book_open_variant_24dp
|
||||
(viewer as? PagerViewer)?.config?.splitPages == true -> R.drawable.ic_book_open_split_24dp
|
||||
else -> R.drawable.ic_single_page_24dp
|
||||
}
|
||||
)
|
||||
)
|
||||
with(binding.readerNav) {
|
||||
@ -354,11 +358,6 @@ class ReaderActivity :
|
||||
}
|
||||
}
|
||||
}
|
||||
binding.chaptersSheet.doublePage.compatToolTipText =
|
||||
getString(
|
||||
if (isDoublePage) R.string.switch_to_single
|
||||
else R.string.switch_to_double
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateOrientationShortcut(preference: Int) {
|
||||
@ -554,14 +553,39 @@ class ReaderActivity :
|
||||
}
|
||||
|
||||
with(binding.chaptersSheet) {
|
||||
doublePage.setOnClickListener {
|
||||
if (preferences.pageLayout().get() == PageLayout.AUTOMATIC.value) {
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
config.doublePages = !config.doublePages
|
||||
reloadChapters(config.doublePages, true)
|
||||
with(doublePage) {
|
||||
compatToolTipText = getString(R.string.page_layout)
|
||||
setOnClickListener {
|
||||
val config = (viewer as? PagerViewer)?.config
|
||||
val selectedId = when {
|
||||
config?.doublePages == true -> PageLayout.DOUBLE_PAGES
|
||||
config?.splitPages == true -> PageLayout.SPLIT_PAGES
|
||||
else -> PageLayout.SINGLE_PAGE
|
||||
}
|
||||
popupMenu(
|
||||
items = listOf(
|
||||
PageLayout.SINGLE_PAGE,
|
||||
PageLayout.DOUBLE_PAGES,
|
||||
PageLayout.SPLIT_PAGES,
|
||||
).map { it.value to it.stringRes },
|
||||
selectedItemId = selectedId.value,
|
||||
) {
|
||||
val newLayout = PageLayout.fromPreference(itemId)
|
||||
|
||||
if (preferences.pageLayout().get() == PageLayout.AUTOMATIC.value) {
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
config.doublePages = newLayout == PageLayout.DOUBLE_PAGES
|
||||
if (newLayout == PageLayout.SINGLE_PAGE) {
|
||||
preferences.automaticSplitsPage().set(false)
|
||||
} else if (newLayout == PageLayout.SPLIT_PAGES) {
|
||||
preferences.automaticSplitsPage().set(true)
|
||||
}
|
||||
reloadChapters(config.doublePages, true)
|
||||
}
|
||||
} else {
|
||||
preferences.pageLayout().set(newLayout.value)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
preferences.pageLayout().set(1 - preferences.pageLayout().get())
|
||||
}
|
||||
}
|
||||
cropBordersSheetButton.setOnClickListener {
|
||||
@ -917,6 +941,9 @@ class ReaderActivity :
|
||||
setDoublePageMode(pViewer)
|
||||
} else {
|
||||
pViewer.config.doublePages = doublePages
|
||||
if (pViewer.config.autoDoublePages) {
|
||||
pViewer.config.splitPages = preferences.automaticSplitsPage().get() && !pViewer.config.doublePages
|
||||
}
|
||||
}
|
||||
val currentChapter = presenter.getCurrentChapter()
|
||||
if (doublePages) {
|
||||
@ -925,7 +952,7 @@ class ReaderActivity :
|
||||
binding.readerNav.pageSeekbar.progress +
|
||||
(
|
||||
currentChapter?.pages?.take(binding.readerNav.pageSeekbar.progress)
|
||||
?.count { it.fullPage || it.isolatedPage } ?: 0
|
||||
?.count { it.fullPage == true || it.isolatedPage } ?: 0
|
||||
)
|
||||
) % 2 != 0
|
||||
}
|
||||
@ -953,7 +980,7 @@ class ReaderActivity :
|
||||
currentChapter.requestedPage +
|
||||
(
|
||||
currentChapter.pages?.take(currentChapter.requestedPage)
|
||||
?.count { it.fullPage || it.isolatedPage } ?: 0
|
||||
?.count { it.fullPage == true || it.isolatedPage } ?: 0
|
||||
)
|
||||
) % 2 != 0
|
||||
}
|
||||
@ -1042,7 +1069,7 @@ class ReaderActivity :
|
||||
val currentPage = if (hasExtraPage) {
|
||||
if (resources.isLTR) "${page.number}-${page.number + 1}" else "${page.number + 1}-${page.number}"
|
||||
} else {
|
||||
"${page.number}"
|
||||
"${page.number}${if (page.firstHalf == false) "*" else ""}"
|
||||
}
|
||||
|
||||
val totalPages = pages.size.toString()
|
||||
@ -1347,6 +1374,9 @@ class ReaderActivity :
|
||||
private fun setDoublePageMode(viewer: PagerViewer) {
|
||||
val currentOrientation = resources.configuration.orientation
|
||||
viewer.config.doublePages = (currentOrientation == Configuration.ORIENTATION_LANDSCAPE)
|
||||
if (viewer.config.autoDoublePages) {
|
||||
viewer.config.splitPages = preferences.automaticSplitsPage().get() && !viewer.config.doublePages
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleIntentAction(intent: Intent): Boolean {
|
||||
@ -1438,6 +1468,18 @@ class ReaderActivity :
|
||||
|
||||
preferences.pageLayout().asImmediateFlowIn(scope) { setBottomNavButtons(it) }
|
||||
|
||||
preferences.automaticSplitsPage().asFlow()
|
||||
.drop(1)
|
||||
.onEach {
|
||||
val isPaused = !this@ReaderActivity.lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)
|
||||
if (isPaused) {
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
reloadChapters(config.doublePages, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
preferences.readerBottomButtons().asImmediateFlowIn(scope) { updateBottomShortcuts() }
|
||||
|
||||
preferences.readWithTapping().asImmediateFlowIn(scope) {
|
||||
|
@ -490,7 +490,7 @@ class ReaderPresenter(
|
||||
if (shouldTrack &&
|
||||
// For double pages, check if the second to last page is doubled up
|
||||
(
|
||||
selectedChapter.pages?.lastIndex == page.index ||
|
||||
(selectedChapter.pages?.lastIndex == page.index && page.firstHalf != true) ||
|
||||
(hasExtraPage && selectedChapter.pages?.lastIndex?.minus(1) == page.index)
|
||||
)
|
||||
) {
|
||||
|
@ -0,0 +1,16 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.model
|
||||
|
||||
class InsertPage(parent: ReaderPage) : ReaderPage(
|
||||
parent.index,
|
||||
parent.url,
|
||||
parent.imageUrl
|
||||
) {
|
||||
|
||||
override var chapter: ReaderChapter = parent.chapter
|
||||
|
||||
init {
|
||||
fullPage = true
|
||||
firstHalf = false
|
||||
stream = parent.stream
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ import android.graphics.drawable.Drawable
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import java.io.InputStream
|
||||
|
||||
class ReaderPage(
|
||||
open class ReaderPage(
|
||||
index: Int,
|
||||
url: String = "",
|
||||
imageUrl: String? = null,
|
||||
@ -14,15 +14,21 @@ class ReaderPage(
|
||||
/** Value to check if this page is used to as if it was too wide */
|
||||
var shiftedPage: Boolean = false,
|
||||
/** Value to check if a page is can be doubled up, but can't because the next page is too wide */
|
||||
var isolatedPage: Boolean = false
|
||||
var isolatedPage: Boolean = false,
|
||||
var firstHalf: Boolean? = null,
|
||||
var longPage: Boolean? = null
|
||||
) : Page(index, url, imageUrl, null) {
|
||||
|
||||
lateinit var chapter: ReaderChapter
|
||||
open lateinit var chapter: ReaderChapter
|
||||
|
||||
/** Value to check if a page is too wide to be doubled up */
|
||||
var fullPage: Boolean = false
|
||||
var fullPage: Boolean? = null
|
||||
set(value) {
|
||||
field = value
|
||||
if (value) shiftedPage = false
|
||||
longPage = value
|
||||
if (value == true) shiftedPage = false
|
||||
}
|
||||
|
||||
fun isFromSamePage(page: ReaderPage): Boolean =
|
||||
index == page.index && chapter.chapter.id == page.chapter.chapter.id
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ enum class PageLayout(val value: Int, @StringRes val stringRes: Int, @StringRes
|
||||
SINGLE_PAGE(0, R.string.single_page),
|
||||
DOUBLE_PAGES(1, R.string.double_pages),
|
||||
AUTOMATIC(2, R.string.automatic, R.string.automatic_orientation),
|
||||
SPLIT_PAGES(3, R.string.split_double_pages)
|
||||
;
|
||||
|
||||
@StringRes val fullStringRes = _fullStringRes ?: stringRes
|
||||
|
@ -58,6 +58,9 @@ class PagerConfig(
|
||||
|
||||
var autoDoublePages = preferences.pageLayout().get() == PageLayout.AUTOMATIC.value
|
||||
|
||||
var splitPages = preferences.pageLayout().get() == PageLayout.SPLIT_PAGES.value
|
||||
var autoSplitPages = preferences.automaticSplitsPage().get()
|
||||
|
||||
init {
|
||||
preferences.pageTransitions()
|
||||
.register({ usePageTransitions = it })
|
||||
@ -103,6 +106,7 @@ class PagerConfig(
|
||||
.drop(1)
|
||||
.onEach {
|
||||
autoDoublePages = it == PageLayout.AUTOMATIC.value
|
||||
splitPages = it == PageLayout.SPLIT_PAGES.value
|
||||
if (!autoDoublePages) {
|
||||
doublePages = it == PageLayout.DOUBLE_PAGES.value
|
||||
}
|
||||
@ -114,9 +118,12 @@ class PagerConfig(
|
||||
autoDoublePages = it == PageLayout.AUTOMATIC.value
|
||||
if (!autoDoublePages) {
|
||||
doublePages = it == PageLayout.DOUBLE_PAGES.value
|
||||
splitPages = it == PageLayout.SPLIT_PAGES.value
|
||||
}
|
||||
})
|
||||
|
||||
preferences.automaticSplitsPage()
|
||||
.register({ autoSplitPages = it })
|
||||
navigationOverlayForNewUser = preferences.showNavigationOverlayNewUser().get()
|
||||
if (navigationOverlayForNewUser) {
|
||||
preferences.showNavigationOverlayNewUser().set(false)
|
||||
|
@ -348,7 +348,7 @@ class PagerPageHolder(
|
||||
val stream = streamFn().buffered(16)
|
||||
|
||||
val stream2 = if (extraPage != null) streamFn2?.invoke()?.buffered(16) else null
|
||||
openStream = this@PagerPageHolder.mergePages(stream, stream2)
|
||||
openStream = this@PagerPageHolder.mergeOrSplitPages(stream, stream2)
|
||||
ImageUtil.isAnimatedAndSupported(stream) ||
|
||||
if (stream2 != null) ImageUtil.isAnimatedAndSupported(stream2) else false
|
||||
}
|
||||
@ -507,6 +507,15 @@ class PagerPageHolder(
|
||||
}
|
||||
setOnImageEventListener(
|
||||
object : SubsamplingScaleImageView.DefaultOnImageEventListener() {
|
||||
|
||||
override fun onImageLoaded() {
|
||||
if (this@PagerPageHolder.extraPage == null &&
|
||||
this@PagerPageHolder.page.longPage == null &&
|
||||
sHeight < sWidth
|
||||
) {
|
||||
this@PagerPageHolder.page.longPage = true
|
||||
}
|
||||
}
|
||||
override fun onReady() {
|
||||
var centerV = 0f
|
||||
when (config.imageZoomType) {
|
||||
@ -651,9 +660,63 @@ class PagerPageHolder(
|
||||
return decodeLayout
|
||||
}
|
||||
|
||||
private fun mergePages(imageStream: InputStream, imageStream2: InputStream?): InputStream {
|
||||
imageStream2 ?: return imageStream
|
||||
if (page.fullPage) return imageStream
|
||||
private fun mergeOrSplitPages(imageStream: InputStream, imageStream2: InputStream?): InputStream {
|
||||
if (page.longPage == true && viewer.config.splitPages) {
|
||||
val imageBytes = imageStream.readBytes()
|
||||
val imageBitmap = try {
|
||||
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||
} catch (e: Exception) {
|
||||
imageStream.close()
|
||||
Timber.e("Cannot split page ${e.message}")
|
||||
return imageBytes.inputStream()
|
||||
}
|
||||
val isLTR = (viewer !is R2LPagerViewer).xor(viewer.config.invertDoublePages)
|
||||
return ImageUtil.splitBitmap(imageBitmap, (page.firstHalf == false).xor(!isLTR)) {
|
||||
scope?.launchUI {
|
||||
if (it == 100) {
|
||||
progressBar.completeAndFadeOut()
|
||||
} else {
|
||||
progressBar.setProgress(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (imageStream2 == null) {
|
||||
if (viewer.config.splitPages && page.longPage == null) {
|
||||
val imageBytes = imageStream.readBytes()
|
||||
val imageBitmap = try {
|
||||
BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
|
||||
} catch (e: Exception) {
|
||||
imageStream.close()
|
||||
page.longPage = true
|
||||
skipExtra = true
|
||||
Timber.e("Cannot split page ${e.message}")
|
||||
return imageBytes.inputStream()
|
||||
}
|
||||
val height = imageBitmap.height
|
||||
val width = imageBitmap.width
|
||||
return if (height < width) {
|
||||
imageStream.close()
|
||||
page.longPage = true
|
||||
skipExtra = true
|
||||
val isLTR = (viewer !is R2LPagerViewer).xor(viewer.config.invertDoublePages)
|
||||
return ImageUtil.splitBitmap(imageBitmap, !isLTR) {
|
||||
scope?.launchUI {
|
||||
if (it == 100) {
|
||||
progressBar.completeAndFadeOut()
|
||||
} else {
|
||||
progressBar.setProgress(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
page.longPage = false
|
||||
imageBytes.inputStream()
|
||||
}
|
||||
}
|
||||
return imageStream
|
||||
}
|
||||
if (page.fullPage == true) return imageStream
|
||||
if (ImageUtil.isAnimatedAndSupported(imageStream)) {
|
||||
page.fullPage = true
|
||||
skipExtra = true
|
||||
@ -732,7 +795,7 @@ class PagerPageHolder(
|
||||
}
|
||||
|
||||
private fun splitDoublePages() {
|
||||
extraPage ?: return
|
||||
// extraPage ?: return
|
||||
viewer.splitDoublePages(page)
|
||||
if (extraPage?.fullPage == true) {
|
||||
extraPage = null
|
||||
|
@ -156,7 +156,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
||||
val allowPreload = checkAllowPreload(page.first as? ReaderPage)
|
||||
currentPage = page.first
|
||||
when (val aPage = page.first) {
|
||||
is ReaderPage -> onReaderPageSelected(aPage, allowPreload, page.second != null)
|
||||
is ReaderPage -> onReaderPageSelected(
|
||||
aPage,
|
||||
allowPreload,
|
||||
page.second is ReaderPage
|
||||
)
|
||||
is ChapterTransition -> onTransitionSelected(aPage)
|
||||
}
|
||||
}
|
||||
@ -275,7 +279,14 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
||||
*/
|
||||
override fun moveToPage(page: ReaderPage, animated: Boolean) {
|
||||
Timber.d("moveToPage ${page.number}")
|
||||
val position = adapter.joinedItems.indexOfFirst { it.first == page || it.second == page }
|
||||
val position = adapter.joinedItems.indexOfFirst {
|
||||
it.first == page || it.second == page ||
|
||||
(
|
||||
config.splitPages && it.first is ReaderPage &&
|
||||
(it.first as? ReaderPage)?.isFromSamePage(page) == true &&
|
||||
(it.first as? ReaderPage)?.firstHalf != false
|
||||
)
|
||||
}
|
||||
if (position != -1) {
|
||||
val currentPosition = pager.currentItem
|
||||
pager.setCurrentItem(position, animated)
|
||||
@ -288,7 +299,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
||||
val joinedItem = adapter.joinedItems.firstOrNull { it.first == page || it.second == page }
|
||||
activity.onPageSelected(
|
||||
joinedItem?.first as? ReaderPage ?: page,
|
||||
joinedItem?.second != null
|
||||
joinedItem?.second is ReaderPage
|
||||
)
|
||||
}
|
||||
} else {
|
||||
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||
import eu.kanade.tachiyomi.ui.reader.model.InsertPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||
@ -55,7 +56,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
// however we should take account full pages when deciding
|
||||
val numberOfFullPages =
|
||||
(
|
||||
chapters.prevChapter.pages?.count { it.fullPage || it.isolatedPage }
|
||||
chapters.prevChapter.pages?.count { it.fullPage == true || it.isolatedPage }
|
||||
?: 0
|
||||
)
|
||||
if (prevPages != null) {
|
||||
@ -134,7 +135,8 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
override fun getItemPosition(view: Any): Int {
|
||||
if (view is PositionableView) {
|
||||
val position = joinedItems.indexOfFirst {
|
||||
view.item == (it.first to it.second)
|
||||
val secondPage = it.second as? ReaderPage
|
||||
view.item == it.first to secondPage
|
||||
}
|
||||
if (position != -1) {
|
||||
return position
|
||||
@ -148,13 +150,17 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
fun splitDoublePages(current: ReaderPage) {
|
||||
val oldCurrent = joinedItems.getOrNull(viewer.pager.currentItem)
|
||||
setJoinedItems(
|
||||
oldCurrent?.second == current ||
|
||||
(current.index + 1) < (
|
||||
(
|
||||
oldCurrent?.second
|
||||
?: oldCurrent?.first
|
||||
) as? ReaderPage
|
||||
)?.index ?: 0
|
||||
if (viewer.config.splitPages) {
|
||||
(oldCurrent?.first as? ReaderPage)?.firstHalf == false
|
||||
} else {
|
||||
oldCurrent?.second == current ||
|
||||
(current.index + 1) < (
|
||||
(
|
||||
oldCurrent?.second
|
||||
?: oldCurrent?.first
|
||||
) as? ReaderPage
|
||||
)?.index ?: 0
|
||||
}
|
||||
)
|
||||
|
||||
// The listener may be removed when we split a page, so the ui may not have updated properly
|
||||
@ -170,8 +176,36 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
// If not in double mode, set up items like before
|
||||
subItems.forEach {
|
||||
(it as? ReaderPage)?.shiftedPage = false
|
||||
(it as? ReaderPage)?.firstHalf = null
|
||||
}
|
||||
if (viewer.config.splitPages) {
|
||||
var itemIndex = 0
|
||||
val pagedItems = subItems.toMutableList()
|
||||
while (itemIndex < pagedItems.size) {
|
||||
val page = pagedItems[itemIndex] as? ReaderPage
|
||||
if (page == null) {
|
||||
itemIndex++
|
||||
continue
|
||||
}
|
||||
if (page.longPage == true) {
|
||||
page.firstHalf = true
|
||||
// Add a second halved page after each full page.
|
||||
pagedItems[itemIndex] = InsertPage(page).apply { firstHalf = true }
|
||||
val secondHalf = InsertPage(page)
|
||||
pagedItems.add(itemIndex + 1, secondHalf)
|
||||
itemIndex++
|
||||
}
|
||||
itemIndex++
|
||||
}
|
||||
this.joinedItems = pagedItems.map {
|
||||
Pair<Any, Any?>(
|
||||
it,
|
||||
if ((it as? ReaderPage)?.fullPage == true) (it as? ReaderPage)?.firstHalf else null
|
||||
)
|
||||
}.toMutableList()
|
||||
} else {
|
||||
this.joinedItems = subItems.map { Pair<Any, Any?>(it, null) }.toMutableList()
|
||||
}
|
||||
this.joinedItems = subItems.map { Pair<Any, Any?>(it, null) }.toMutableList()
|
||||
if (viewer is R2LPagerViewer) {
|
||||
joinedItems.reverse()
|
||||
}
|
||||
@ -200,6 +234,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
|
||||
items.forEach {
|
||||
it?.shiftedPage = false
|
||||
it?.firstHalf = null
|
||||
}
|
||||
// Step 3: If pages have been shifted,
|
||||
if (viewer.config.shiftDoublePage) {
|
||||
@ -221,7 +256,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
)
|
||||
// Add a shifted page to the first place there isnt a full page
|
||||
(fullPageBeforeIndex until items.size).forEach {
|
||||
if (items[it]?.fullPage == false) {
|
||||
if (items[it]?.fullPage != true) {
|
||||
items[it]?.shiftedPage = true
|
||||
return@loop
|
||||
}
|
||||
@ -281,10 +316,23 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
when {
|
||||
(oldCurrent?.first as? ReaderPage)?.chapter != currentChapter &&
|
||||
(oldCurrent?.first as? ChapterTransition)?.from != currentChapter -> subItems.find { (it as? ReaderPage)?.chapter == currentChapter }
|
||||
useSecondPage -> (oldCurrent?.second ?: oldCurrent?.first)
|
||||
useSecondPage && oldCurrent?.second is ReaderPage -> (oldCurrent.second ?: oldCurrent.first)
|
||||
else -> oldCurrent?.first ?: return
|
||||
}
|
||||
var index = joinedItems.indexOfFirst { it.first == newPage || it.second == newPage }
|
||||
var index = joinedItems.indexOfFirst {
|
||||
val readerPage = it.first as? ReaderPage
|
||||
val readerPage2 = it.second as? ReaderPage
|
||||
val newReaderPage = newPage as? ReaderPage
|
||||
it.first == newPage || it.second == newPage ||
|
||||
(
|
||||
readerPage != null && newReaderPage != null &&
|
||||
(
|
||||
readerPage.isFromSamePage(newReaderPage) ||
|
||||
readerPage2?.isFromSamePage(newReaderPage) == true
|
||||
) &&
|
||||
(readerPage.firstHalf == !useSecondPage || readerPage.firstHalf == null)
|
||||
)
|
||||
}
|
||||
if (newPage is ChapterTransition && index == -1 && !forceTransition) {
|
||||
val newerPage = if (newPage is ChapterTransition.Next) {
|
||||
joinedItems.filter {
|
||||
@ -297,6 +345,8 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||
}
|
||||
index = joinedItems.indexOfFirst { it.first == newerPage || it.second == newerPage }
|
||||
}
|
||||
viewer.pager.setCurrentItem(index, false)
|
||||
if (index > -1) {
|
||||
viewer.pager.setCurrentItem(index, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -255,6 +255,12 @@ class SettingsReaderController : SettingsController() {
|
||||
infoPreference(R.string.automatic_can_still_switch).apply {
|
||||
preferences.pageLayout().asImmediateFlowIn(viewScope) { isVisible = it == PageLayout.AUTOMATIC.value }
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.automaticSplitsPage
|
||||
titleRes = R.string.split_double_pages_portrait
|
||||
defaultValue = false
|
||||
preferences.pageLayout().asImmediateFlowIn(viewScope) { isVisible = it == PageLayout.AUTOMATIC.value }
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.invertDoublePages
|
||||
titleRes = R.string.invert_double_pages
|
||||
|
@ -278,6 +278,24 @@ object ImageUtil {
|
||||
return ColorDrawable(backgroundColor)
|
||||
}
|
||||
|
||||
fun splitBitmap(
|
||||
imageBitmap: Bitmap,
|
||||
secondHalf: Boolean,
|
||||
progressCallback: ((Int) -> Unit)? = null
|
||||
): ByteArrayInputStream {
|
||||
val height = imageBitmap.height
|
||||
val width = imageBitmap.width
|
||||
val result = Bitmap.createBitmap(width / 2, height, Bitmap.Config.ARGB_8888)
|
||||
val canvas = Canvas(result)
|
||||
progressCallback?.invoke(98)
|
||||
canvas.drawBitmap(imageBitmap, Rect(if (!secondHalf) 0 else width / 2, 0, if (secondHalf) width else width / 2, height), result.rect, null)
|
||||
progressCallback?.invoke(99)
|
||||
val output = ByteArrayOutputStream()
|
||||
result.compress(Bitmap.CompressFormat.JPEG, 100, output)
|
||||
progressCallback?.invoke(100)
|
||||
return ByteArrayInputStream(output.toByteArray())
|
||||
}
|
||||
|
||||
fun mergeBitmaps(
|
||||
imageBitmap: Bitmap,
|
||||
imageBitmap2: Bitmap,
|
||||
|
9
app/src/main/res/drawable/ic_book_open_split_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_book_open_split_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M13.9,12h6.5v1.4h-6.5M13.9,9.7h6.5v1.4h-6.5M13.9,14.4h6.5v1.4h-6.5M21.3,4.6H13l0.6,1L13,6.5v12.1l0.6,0.9L13,20.4h8.4c1,0 1.9,-0.8 1.9,-1.9V6.5C23.2,5.4 22.3,4.6 21.3,4.6M21.3,18.5H13V6.5h8.4M7.3,4.6H3c-1,0 -1.9,0.8 -1.9,1.9v12.1c0,1 0.8,1.9 1.9,1.9h8.4l-1.1,-1.9l1.1,-2.2l-1,-1.8l1,-2l-0.9,-2.2l0.9,-1.8l-0.9,-2l0.9,-1.9"/>
|
||||
</vector>
|
@ -113,6 +113,7 @@
|
||||
<item>@string/single_page</item>
|
||||
<item>@string/double_pages</item>
|
||||
<item>@string/automatic</item>
|
||||
<item>@string/split_double_pages</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="invert_tapping_mode">
|
||||
|
@ -382,6 +382,7 @@
|
||||
<string name="reduces_banding_impacts_performance">Reduces banding, but impacts
|
||||
performance</string>
|
||||
<string name="invert_double_pages">Invert double pages</string>
|
||||
<string name="split_double_pages_portrait">Split double pages in portrait</string>
|
||||
<string name="crop_borders">Crop borders</string>
|
||||
<string name="crop_borders_paged">Crop borders (Paged)</string>
|
||||
<string name="crop_borders_webtoon">Crop borders (Webtoon)</string>
|
||||
@ -421,6 +422,7 @@
|
||||
<string name="original_size">Original size</string>
|
||||
<string name="smart_fit">Smart fit</string>
|
||||
<string name="zoom_start_position">Zoom start position</string>
|
||||
<string name="split_double_pages">Split double pages</string>
|
||||
<string name="double_pages">Double pages</string>
|
||||
<string name="single_page">Single page</string>
|
||||
<string name="switch_to_double">Switch to double pages</string>
|
||||
|
Loading…
Reference in New Issue
Block a user