Remove beta webtoon viewer split page

This had a bunch of issues around split pages not showing up properly so things
end up appearing to be missing while reading.
It'd be more worthwhile redoing the reader viewers than trying to get this to work
properly. It'd be better to just enable the split pages on download instead.

Closes #8433
This commit is contained in:
arkon 2023-10-08 16:23:57 -04:00
parent 6dab94a937
commit 94cba9324c
14 changed files with 9 additions and 188 deletions

View file

@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import tachiyomi.presentation.core.util.collectAsState import tachiyomi.presentation.core.util.collectAsState
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -305,12 +304,6 @@ object SettingsReaderScreen : SearchableSettings {
subtitle = stringResource(R.string.pref_dual_page_invert_summary), subtitle = stringResource(R.string.pref_dual_page_invert_summary),
enabled = dualPageSplit, enabled = dualPageSplit,
), ),
Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.longStripSplitWebtoon(),
title = stringResource(R.string.pref_long_strip_split),
subtitle = stringResource(R.string.split_tall_images_summary),
enabled = !isReleaseBuildType, // TODO: Show in release build when the feature is stable
),
Preference.PreferenceItem.SwitchPreference( Preference.PreferenceItem.SwitchPreference(
pref = readerPreferences.webtoonDoubleTapZoomEnabled(), pref = readerPreferences.webtoonDoubleTapZoomEnabled(),
title = stringResource(R.string.pref_double_tap_zoom), title = stringResource(R.string.pref_double_tap_zoom),

View file

@ -16,7 +16,6 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsScreenModel
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import tachiyomi.presentation.core.components.CheckboxItem import tachiyomi.presentation.core.components.CheckboxItem
import tachiyomi.presentation.core.components.HeadingItem import tachiyomi.presentation.core.components.HeadingItem
import tachiyomi.presentation.core.components.SettingsChipRow import tachiyomi.presentation.core.components.SettingsChipRow
@ -185,13 +184,6 @@ private fun ColumnScope.WebtoonViewerSettings(screenModel: ReaderSettingsScreenM
) )
} }
if (!isReleaseBuildType) {
CheckboxItem(
label = stringResource(R.string.pref_long_strip_split),
pref = screenModel.preferences.longStripSplitWebtoon(),
)
}
CheckboxItem( CheckboxItem(
label = stringResource(R.string.pref_double_tap_zoom), label = stringResource(R.string.pref_double_tap_zoom),
pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(), pref = screenModel.preferences.webtoonDoubleTapZoomEnabled(),

View file

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import tachiyomi.core.preference.Preference import tachiyomi.core.preference.Preference
@ -363,13 +362,6 @@ object Migrations {
if (oldVersion < 100) { if (oldVersion < 100) {
BackupCreateJob.setupTask(context) BackupCreateJob.setupTask(context)
} }
if (oldVersion < 102) {
// This was accidentally visible from the reader settings sheet, but should always
// be disabled in release builds.
if (isReleaseBuildType) {
readerPreferences.longStripSplitWebtoon().set(false)
}
}
if (oldVersion < 105) { if (oldVersion < 105) {
val pref = libraryPreferences.autoUpdateDeviceRestrictions() val pref = libraryPreferences.autoUpdateDeviceRestrictions()
if (pref.isSet() && "battery_not_low" in pref.get()) { if (pref.isSet() && "battery_not_low" in pref.get()) {

View file

@ -58,5 +58,8 @@ class BackupFileValidator(
return Results(missingSources, missingTrackers) return Results(missingSources, missingTrackers)
} }
data class Results(val missingSources: List<String>, val missingTrackers: List<String>) data class Results(
val missingSources: List<String>,
val missingTrackers: List<String>,
)
} }

View file

@ -26,7 +26,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
val uri = inputData.getString(LOCATION_URI_KEY)?.toUri() val uri = inputData.getString(LOCATION_URI_KEY)?.toUri()
?: return Result.failure() ?: return Result.failure()
val sync = inputData.getBoolean(SYNC, false) val sync = inputData.getBoolean(SYNC_KEY, false)
try { try {
setForeground(getForegroundInfo()) setForeground(getForegroundInfo())
@ -67,7 +67,7 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
fun start(context: Context, uri: Uri, sync: Boolean = false) { fun start(context: Context, uri: Uri, sync: Boolean = false) {
val inputData = workDataOf( val inputData = workDataOf(
LOCATION_URI_KEY to uri.toString(), LOCATION_URI_KEY to uri.toString(),
SYNC to sync, SYNC_KEY to sync,
) )
val request = OneTimeWorkRequestBuilder<BackupRestoreJob>() val request = OneTimeWorkRequestBuilder<BackupRestoreJob>()
.addTag(TAG) .addTag(TAG)
@ -85,5 +85,4 @@ class BackupRestoreJob(private val context: Context, workerParams: WorkerParamet
private const val TAG = "BackupRestore" private const val TAG = "BackupRestore"
private const val LOCATION_URI_KEY = "location_uri" // String private const val LOCATION_URI_KEY = "location_uri" // String
private const val SYNC_KEY = "sync" // Boolean
private const val SYNC = "sync" // Boolean

View file

@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.ui.reader.loader.DownloadPageLoader
import eu.kanade.tachiyomi.ui.reader.model.InsertPage import eu.kanade.tachiyomi.ui.reader.model.InsertPage
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage 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.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
@ -405,8 +404,8 @@ class ReaderViewModel @JvmOverloads constructor(
* [page]'s chapter is different from the currently active. * [page]'s chapter is different from the currently active.
*/ */
fun onPageSelected(page: ReaderPage) { fun onPageSelected(page: ReaderPage) {
// InsertPage and StencilPage doesn't change page progress // InsertPage doesn't change page progress
if (page is InsertPage || page is StencilPage) { if (page is InsertPage) {
return return
} }

View file

@ -1,16 +0,0 @@
package eu.kanade.tachiyomi.ui.reader.model
import java.io.InputStream
class StencilPage(
parent: ReaderPage,
stencilStream: () -> InputStream,
) : ReaderPage(parent.index, parent.url, parent.imageUrl) {
override var chapter: ReaderChapter = parent.chapter
init {
status = State.READY
stream = stencilStream
}
}

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.reader.setting
import androidx.annotation.StringRes import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.core.preference.getEnum import tachiyomi.core.preference.getEnum
@ -33,9 +32,6 @@ class ReaderPreferences(
fun defaultOrientationType() = preferenceStore.getInt("pref_default_orientation_type_key", OrientationType.FREE.flagValue) fun defaultOrientationType() = preferenceStore.getInt("pref_default_orientation_type_key", OrientationType.FREE.flagValue)
// TODO: Enable in release build when the feature is stable
fun longStripSplitWebtoon() = preferenceStore.getBoolean("pref_long_strip_split_webtoon", !isReleaseBuildType)
fun webtoonDoubleTapZoomEnabled() = preferenceStore.getBoolean("pref_enable_double_tap_zoom_webtoon", true) fun webtoonDoubleTapZoomEnabled() = preferenceStore.getBoolean("pref_enable_double_tap_zoom_webtoon", true)
fun imageScaleType() = preferenceStore.getInt("pref_image_scale_type_key", 1) fun imageScaleType() = preferenceStore.getInt("pref_image_scale_type_key", 1)

View file

@ -7,12 +7,10 @@ import androidx.recyclerview.widget.RecyclerView
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage 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.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView import eu.kanade.tachiyomi.ui.reader.viewer.ReaderPageImageView
import eu.kanade.tachiyomi.ui.reader.viewer.calculateChapterGap import eu.kanade.tachiyomi.ui.reader.viewer.calculateChapterGap
import eu.kanade.tachiyomi.util.system.createReaderThemeContext import eu.kanade.tachiyomi.util.system.createReaderThemeContext
import tachiyomi.core.util.system.logcat
/** /**
* RecyclerView Adapter used by this [viewer] to where [ViewerChapters] updates are posted. * RecyclerView Adapter used by this [viewer] to where [ViewerChapters] updates are posted.
@ -27,27 +25,6 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter<RecyclerV
var currentChapter: ReaderChapter? = null var currentChapter: ReaderChapter? = null
fun onLongStripSplit(currentStrip: Any?, newStrips: List<StencilPage>) {
if (newStrips.isEmpty()) return
if (currentStrip is StencilPage) return
val placeAtIndex = items.indexOf(currentStrip) + 1
// Stop constantly adding split images
if (items.getOrNull(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 * Context that has been wrapped to use the correct theme values based on the
* current app theme and reader background color * current app theme and reader background color

View file

@ -32,11 +32,6 @@ class WebtoonConfig(
var sidePadding = 0 var sidePadding = 0
private set private set
var longStripSplit = false
private set
var longStripSplitChangedListener: ((Boolean) -> Unit)? = null
var doubleTapZoom = true var doubleTapZoom = true
private set private set
@ -67,15 +62,6 @@ class WebtoonConfig(
readerPreferences.dualPageInvertWebtoon() readerPreferences.dualPageInvertWebtoon()
.register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() }) .register({ dualPageInvert = it }, { imagePropertyChangedListener?.invoke() })
readerPreferences.longStripSplitWebtoon()
.register(
{ longStripSplit = it },
{
imagePropertyChangedListener?.invoke()
longStripSplitChangedListener?.invoke(it)
},
)
readerPreferences.webtoonDoubleTapZoomEnabled() readerPreferences.webtoonDoubleTapZoomEnabled()
.register( .register(
{ doubleTapZoom = it }, { doubleTapZoom = it },

View file

@ -13,7 +13,6 @@ import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import eu.kanade.tachiyomi.databinding.ReaderErrorBinding import eu.kanade.tachiyomi.databinding.ReaderErrorBinding
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage 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.ReaderPageImageView
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.ui.webview.WebViewActivity
@ -24,12 +23,10 @@ import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope import kotlinx.coroutines.supervisorScope
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import logcat.LogPriority
import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.launchIO
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.lang.withUIContext
import tachiyomi.core.util.system.ImageUtil import tachiyomi.core.util.system.ImageUtil
import tachiyomi.core.util.system.logcat
import java.io.BufferedInputStream import java.io.BufferedInputStream
import java.io.InputStream import java.io.InputStream
@ -221,40 +218,9 @@ class WebtoonPageHolder(
} }
} }
if (viewer.config.longStripSplit) {
if (page is StencilPage) {
return imageStream
}
val isStripSplitNeeded = ImageUtil.isStripSplitNeeded(imageStream)
if (isStripSplitNeeded) {
return onStripSplit(imageStream)
}
}
return imageStream return imageStream
} }
private fun onStripSplit(imageStream: BufferedInputStream): InputStream {
try {
// If we have reached this point [page] and its stream shouldn't be null
val page = page!!
val stream = page.stream!!
val splitData = ImageUtil.getSplitDataForStream(imageStream).toMutableList()
val currentSplitData = splitData.removeFirst()
val newPages = splitData.map {
StencilPage(page) { ImageUtil.splitStrip(it, stream) }
}
return ImageUtil.splitStrip(currentSplitData) { imageStream }
.also {
// Running [onLongStripSplit] first results in issues with splitting
viewer.onLongStripSplit(page, newPages)
}
} catch (e: Exception) {
logcat(LogPriority.ERROR, e) { "Failed to split image" }
return imageStream
}
}
/** /**
* Called when the page has an error. * Called when the page has an error.
*/ */

View file

@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage 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.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
@ -151,12 +150,6 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart) activity.binding.navigationOverlay.setNavigation(config.navigator, showOnStart)
} }
config.longStripSplitChangedListener = { enabled ->
if (!enabled) {
cleanupSplitStrips()
}
}
frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT) frame.layoutParams = ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)
frame.addView(recycler) frame.addView(recycler)
} }
@ -205,11 +198,6 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
logcat { "onPageSelected: ${page.number}/${pages.size}" } logcat { "onPageSelected: ${page.number}/${pages.size}" }
activity.onPageSelected(page) activity.onPageSelected(page)
// Skip preload on StencilPage
if (page is StencilPage) {
return
}
// Preload next chapter once we're within the last 5 pages of the current chapter // Preload next chapter once we're within the last 5 pages of the current chapter
val inPreloadRange = pages.size - page.number < 5 val inPreloadRange = pages.size - page.number < 5
if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) { if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) {
@ -359,15 +347,4 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
min(position + 3, adapter.itemCount - 1), 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()
}
} }

View file

@ -273,48 +273,6 @@ object ImageUtil {
private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(index + 1)}.jpg" private fun splitImageName(filenamePrefix: String, index: Int) = "${filenamePrefix}__${"%03d".format(index + 1)}.jpg"
/**
* Check whether the image is a long Strip that needs splitting
* @return true if the image is not animated and it's height is greater than image width and screen height
*/
fun isStripSplitNeeded(imageStream: BufferedInputStream): Boolean {
if (isAnimatedAndSupported(imageStream)) return false
val options = extractImageOptions(imageStream)
val imageHeightIsBiggerThanWidth = options.outHeight > options.outWidth
val imageHeightBiggerThanScreenHeight = options.outHeight > optimalImageHeight
return imageHeightIsBiggerThanWidth && imageHeightBiggerThanScreenHeight
}
/**
* Split the imageStream according to the provided splitData
*/
fun splitStrip(splitData: SplitData, streamFn: () -> InputStream): InputStream {
val bitmapRegionDecoder = getBitmapRegionDecoder(streamFn())
?: throw Exception("Failed to create new instance of BitmapRegionDecoder")
logcat {
"WebtoonSplit #${splitData.index} with topOffset=${splitData.topOffset} " +
"splitHeight=${splitData.splitHeight} bottomOffset=${splitData.bottomOffset}"
}
try {
val region = Rect(0, splitData.topOffset, splitData.splitWidth, splitData.bottomOffset)
val splitBitmap = bitmapRegionDecoder.decodeRegion(region, null)
val outputStream = ByteArrayOutputStream()
splitBitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
return ByteArrayInputStream(outputStream.toByteArray())
} catch (e: Throwable) {
throw e
} finally {
bitmapRegionDecoder.recycle()
}
}
fun getSplitDataForStream(imageStream: InputStream): List<SplitData> {
return extractImageOptions(imageStream).splitData
}
private val BitmapFactory.Options.splitData private val BitmapFactory.Options.splitData
get(): List<SplitData> { get(): List<SplitData> {
val imageHeight = outHeight val imageHeight = outHeight

View file

@ -329,7 +329,6 @@
<string name="pref_dual_page_invert_summary">If the placement of the split wide pages don\'t match reading direction</string> <string name="pref_dual_page_invert_summary">If the placement of the split wide pages don\'t match reading direction</string>
<string name="pref_page_rotate">Rotate wide pages to fit</string> <string name="pref_page_rotate">Rotate wide pages to fit</string>
<string name="pref_page_rotate_invert">Flip orientation of rotated wide pages</string> <string name="pref_page_rotate_invert">Flip orientation of rotated wide pages</string>
<string name="pref_long_strip_split">Split tall images (BETA)</string>
<string name="pref_double_tap_zoom">Double tap to zoom</string> <string name="pref_double_tap_zoom">Double tap to zoom</string>
<string name="pref_cutout_short">Show content in cutout area</string> <string name="pref_cutout_short">Show content in cutout area</string>
<string name="pref_page_transitions">Animate page transitions</string> <string name="pref_page_transitions">Animate page transitions</string>