mirror of
https://github.com/mihonapp/mihon.git
synced 2025-11-13 20:48:56 +01:00
Long Strip Split for Webtoon (#5759)
* Long Strip Split for Webtoon * Review Changes * Review Changes 2 + Rebase
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
package eu.kanade.tachiyomi.ui.reader.model
|
||||
|
||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||
|
||||
class StencilPage(
|
||||
parent: ReaderPage,
|
||||
val splitData: ImageUtil.SplitData,
|
||||
) : ReaderPage(parent.index, parent.url, parent.imageUrl) {
|
||||
|
||||
override var chapter: ReaderChapter = parent.chapter
|
||||
|
||||
init {
|
||||
stream = parent.stream
|
||||
}
|
||||
}
|
||||
@@ -86,8 +86,8 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
|
||||
binding.pagerPrefsGroup.cropBorders.bindToPreference(preferences.cropBorders())
|
||||
binding.pagerPrefsGroup.navigatePan.bindToPreference(preferences.navigateToPan())
|
||||
|
||||
// Makes so that dual page invert gets hidden away when turning of dual page split
|
||||
binding.pagerPrefsGroup.dualPageSplit.bindToPreference(preferences.dualPageSplitPaged())
|
||||
// Makes it so that dual page invert gets hidden away when dual page split is turned off
|
||||
preferences.dualPageSplitPaged()
|
||||
.asHotFlow { binding.pagerPrefsGroup.dualPageInvert.isVisible = it }
|
||||
.launchIn((context as ReaderActivity).lifecycleScope)
|
||||
@@ -110,11 +110,12 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
|
||||
binding.webtoonPrefsGroup.cropBordersWebtoon.bindToPreference(preferences.cropBordersWebtoon())
|
||||
binding.webtoonPrefsGroup.webtoonSidePadding.bindToIntPreference(preferences.webtoonSidePadding(), R.array.webtoon_side_padding_values)
|
||||
|
||||
// Makes so that dual page invert gets hidden away when turning of dual page split
|
||||
binding.webtoonPrefsGroup.dualPageSplit.bindToPreference(preferences.dualPageSplitWebtoon())
|
||||
// Makes it so that dual page invert gets hidden away when dual page split is turned off
|
||||
preferences.dualPageSplitWebtoon()
|
||||
.asHotFlow { binding.webtoonPrefsGroup.dualPageInvert.isVisible = it }
|
||||
.launchIn((context as ReaderActivity).lifecycleScope)
|
||||
binding.webtoonPrefsGroup.dualPageInvert.bindToPreference(preferences.dualPageInvertWebtoon())
|
||||
binding.webtoonPrefsGroup.longStripSplit.bindToPreference(preferences.longStripSplitWebtoon())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,10 +7,12 @@ import androidx.recyclerview.widget.RecyclerView
|
||||
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.StencilPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.hasMissingChapters
|
||||
import eu.kanade.tachiyomi.util.system.createReaderThemeContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
|
||||
/**
|
||||
* RecyclerView Adapter used by this [viewer] to where [ViewerChapters] updates are posted.
|
||||
@@ -25,6 +27,26 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
|
||||
|
||||
var currentChapter: ReaderChapter? = null
|
||||
|
||||
fun onLongStripSplit(currentStrip: Any?, newStrips: List<StencilPage>) {
|
||||
if (currentStrip is StencilPage) return
|
||||
|
||||
val placeAtIndex = items.indexOf(currentStrip) + 1
|
||||
// Stop constantly adding split images
|
||||
if (items[placeAtIndex] is StencilPage) return
|
||||
|
||||
val updatedItems = items.toMutableList()
|
||||
updatedItems.addAll(placeAtIndex, newStrips)
|
||||
updateItems(updatedItems)
|
||||
logcat { "New adapter item count is $itemCount" }
|
||||
}
|
||||
|
||||
fun cleanupSplitStrips() {
|
||||
if (items.any { it is StencilPage }) {
|
||||
val updatedItems = items.filterNot { it is StencilPage }
|
||||
updateItems(updatedItems)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Context that has been wrapped to use the correct theme values based on the
|
||||
* current app theme and reader background color
|
||||
@@ -79,6 +101,10 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
|
||||
}
|
||||
}
|
||||
|
||||
updateItems(newItems)
|
||||
}
|
||||
|
||||
private fun updateItems(newItems: List<Any>) {
|
||||
val result = DiffUtil.calculateDiff(Callback(items, newItems))
|
||||
items = newItems
|
||||
result.dispatchUpdatesTo(this)
|
||||
|
||||
@@ -32,6 +32,11 @@ class WebtoonConfig(
|
||||
var sidePadding = 0
|
||||
private set
|
||||
|
||||
var longStripSplit = false
|
||||
private set
|
||||
|
||||
var longStripSplitChangedListener: ((Boolean) -> Unit)? = null
|
||||
|
||||
val theme = preferences.readerTheme().get()
|
||||
|
||||
init {
|
||||
@@ -57,6 +62,15 @@ class WebtoonConfig(
|
||||
preferences.dualPageInvertWebtoon()
|
||||
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
|
||||
|
||||
preferences.longStripSplitWebtoon()
|
||||
.register(
|
||||
{ longStripSplit = it },
|
||||
{
|
||||
imagePropertyChangedListener?.invoke()
|
||||
longStripSplitChangedListener?.invoke(it)
|
||||
},
|
||||
)
|
||||
|
||||
preferences.readerTheme().asFlow()
|
||||
.drop(1)
|
||||
.distinctUntilChanged()
|
||||
|
||||
@@ -14,10 +14,12 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||
import eu.kanade.tachiyomi.databinding.ReaderErrorBinding
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.StencilPage
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.system.ImageUtil
|
||||
import eu.kanade.tachiyomi.util.system.ImageUtil.SplitData
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import rx.Observable
|
||||
import rx.Subscription
|
||||
@@ -274,17 +276,37 @@ class WebtoonPageHolder(
|
||||
}
|
||||
|
||||
private fun process(imageStream: BufferedInputStream): InputStream {
|
||||
if (!viewer.config.dualPageSplit) {
|
||||
return imageStream
|
||||
if (viewer.config.dualPageSplit) {
|
||||
val isDoublePage = ImageUtil.isWideImage(imageStream)
|
||||
if (isDoublePage) {
|
||||
val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
|
||||
return ImageUtil.splitAndMerge(imageStream, upperSide)
|
||||
}
|
||||
}
|
||||
|
||||
val isDoublePage = ImageUtil.isWideImage(imageStream)
|
||||
if (!isDoublePage) {
|
||||
return imageStream
|
||||
if (viewer.config.longStripSplit) {
|
||||
if (page is StencilPage) {
|
||||
val splitData = (page as StencilPage).splitData
|
||||
return ImageUtil.splitStrip(imageStream, splitData)
|
||||
}
|
||||
|
||||
val isStripSplitNeeded = ImageUtil.isStripSplitNeeded(imageStream)
|
||||
if (isStripSplitNeeded) {
|
||||
val splitData = onStripSplit(imageStream)
|
||||
splitData?.let { return ImageUtil.splitStrip(imageStream, it) }
|
||||
}
|
||||
}
|
||||
|
||||
val upperSide = if (viewer.config.dualPageInvert) ImageUtil.Side.LEFT else ImageUtil.Side.RIGHT
|
||||
return ImageUtil.splitAndMerge(imageStream, upperSide)
|
||||
return imageStream
|
||||
}
|
||||
|
||||
private fun onStripSplit(imageStream: BufferedInputStream): SplitData? {
|
||||
val page = page ?: return null
|
||||
val splitData = ImageUtil.getSplitDataForStream(imageStream).toMutableList()
|
||||
val toReturn = splitData.removeFirstOrNull()
|
||||
val newPages = splitData.map { StencilPage(page, it) }
|
||||
viewer.onLongStripSplit(page, newPages)
|
||||
return toReturn
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.StencilPage
|
||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation.NavigationRegion
|
||||
@@ -154,6 +155,12 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
|
||||
activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart)
|
||||
}
|
||||
|
||||
config.longStripSplitChangedListener = { enabled ->
|
||||
if (!enabled) {
|
||||
cleanupSplitStrips()
|
||||
}
|
||||
}
|
||||
|
||||
frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
|
||||
frame.addView(recycler)
|
||||
}
|
||||
@@ -354,4 +361,15 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
|
||||
min(position + 3, adapter.itemCount - 1),
|
||||
)
|
||||
}
|
||||
|
||||
fun onLongStripSplit(currentStrip: Any?, newStrips: List<StencilPage>) {
|
||||
activity.runOnUiThread {
|
||||
// Need to insert on UI thread else images will go blank
|
||||
adapter.onLongStripSplit(currentStrip, newStrips)
|
||||
}
|
||||
}
|
||||
|
||||
private fun cleanupSplitStrips() {
|
||||
adapter.cleanupSplitStrips()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,6 +289,11 @@ class SettingsReaderController : SettingsController() {
|
||||
summaryRes = R.string.pref_dual_page_invert_summary
|
||||
visibleIf(preferences.dualPageSplitWebtoon()) { it }
|
||||
}
|
||||
switchPreference {
|
||||
bindTo(preferences.longStripSplitWebtoon())
|
||||
titleRes = R.string.pref_long_strip_split
|
||||
summaryRes = R.string.pref_long_strip_split_summary
|
||||
}
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
|
||||
Reference in New Issue
Block a user