Move the reader viewer out of the ViewModel

This commit is contained in:
AntsyLich
2026-10-27 02:38:29 +06:00
parent ced89e3ae1
commit ca028cb657
3 changed files with 20 additions and 25 deletions
@@ -73,6 +73,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReaderSettingsViewModel
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressIndicator
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
import eu.kanade.tachiyomi.ui.reader.viewer.webgpu.WebGpuViewer
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
@@ -82,6 +83,7 @@ import eu.kanade.tachiyomi.util.system.toShareIntent
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.setComposeContent
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.drop
@@ -137,6 +139,12 @@ class ReaderActivity : BaseActivity() {
private var loadingIndicator: ReaderProgressIndicator? = null
/**
* Viewer used to display the pages (pager, webtoon, ...).
*/
private val viewerFlow = MutableStateFlow<Viewer?>(null)
private val viewer: Viewer? inline get() = viewerFlow.value
var isScrollingThroughPages = false
private set
@@ -251,6 +259,7 @@ class ReaderActivity : BaseActivity() {
val settingsviewModel = remember {
ReaderSettingsViewModel(
readerState = viewModel.state,
viewerFlow = viewerFlow,
onChangeReadingMode = viewModel::setMangaReadingMode,
onChangeOrientation = viewModel::setMangaOrientationType,
preferences = readerPreferences,
@@ -337,7 +346,7 @@ class ReaderActivity : BaseActivity() {
*/
override fun onDestroy() {
super.onDestroy()
viewModel.state.value.viewer?.destroy()
viewer?.destroy()
config = null
menuToggleToast?.cancel()
readingModeToast?.cancel()
@@ -408,7 +417,7 @@ class ReaderActivity : BaseActivity() {
* Dispatches a key event. If the viewer doesn't handle it, call the default implementation.
*/
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
val handled = viewModel.state.value.viewer?.handleKeyEvent(event) ?: false
val handled = viewer?.handleKeyEvent(event) ?: false
return handled || super.dispatchKeyEvent(event)
}
@@ -417,7 +426,7 @@ class ReaderActivity : BaseActivity() {
* implementation.
*/
override fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
val handled = viewModel.state.value.viewer?.handleGenericMotionEvent(event) ?: false
val handled = viewer?.handleGenericMotionEvent(event) ?: false
return handled || super.dispatchGenericMotionEvent(event)
}
@@ -446,6 +455,7 @@ class ReaderActivity : BaseActivity() {
@Composable
fun AppBars(state: ReaderViewModel.State) {
val isHttpSource = state.source is HttpSource
val viewer by viewerFlow.collectAsState()
val cropBorderPaged by readerPreferences.cropBorders.collectAsState()
val cropBorderWebtoon by readerPreferences.cropBordersWebtoon.collectAsState()
@@ -473,7 +483,7 @@ class ReaderActivity : BaseActivity() {
onShare = ::shareChapter.takeIf { isHttpSource },
chapterNavigatorType = if (!verticalNavigator) {
if (state.viewer is R2LPagerViewer || (state.viewer as? WebGpuViewer)?.isReversed ?: false) {
if (viewer is R2LPagerViewer || (viewer as? WebGpuViewer)?.isReversed ?: false) {
ChapterNavigatorType.HORIZONTAL_RTL
} else {
ChapterNavigatorType.HORIZONTAL_LTR
@@ -534,7 +544,7 @@ class ReaderActivity : BaseActivity() {
* Called from the presenter when a manga is ready. Used to instantiate the appropriate viewer.
*/
private fun updateViewer() {
val prevViewer = viewModel.state.value.viewer
val prevViewer = viewer
val newViewer = ReadingMode.toViewer(viewModel.getMangaReadingMode(), this)
if (window.sharedElementEnterTransition is MaterialContainerTransform) {
@@ -551,7 +561,7 @@ class ReaderActivity : BaseActivity() {
prevViewer.destroy()
binding.viewerContainer.removeAllViews()
}
viewModel.onViewerLoaded(newViewer)
viewerFlow.value = newViewer
updateViewerInset(readerPreferences.fullscreen.get(), readerPreferences.drawUnderCutout.get())
binding.viewerContainer.addView(newViewer.getView())
@@ -616,7 +626,7 @@ class ReaderActivity : BaseActivity() {
@SuppressLint("RestrictedApi")
private fun setChapters(viewerChapters: ViewerChapters) {
binding.readerContainer.removeView(loadingIndicator)
viewModel.state.value.viewer?.setChapters(viewerChapters)
viewer?.setChapters(viewerChapters)
lifecycleScope.launch(Dispatchers.IO) {
viewModel.getChapterUrl()?.let { url ->
@@ -654,7 +664,7 @@ class ReaderActivity : BaseActivity() {
* page is not found.
*/
private fun moveToPageIndex(index: Int) {
val viewer = viewModel.state.value.viewer ?: return
val viewer = this.viewer ?: return
val currentChapter = viewModel.state.value.currentChapter ?: return
val page = currentChapter.pages?.getOrNull(index) ?: return
viewer.moveToPage(page)
@@ -47,7 +47,6 @@ import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
import eu.kanade.tachiyomi.ui.reader.setting.ReaderOrientation
import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
import eu.kanade.tachiyomi.util.chapter.filterDownloaded
import eu.kanade.tachiyomi.util.chapter.removeDuplicates
import eu.kanade.tachiyomi.util.editCover
@@ -527,12 +526,6 @@ class ReaderViewModel(
eventChannel.trySend(Event.ReloadViewerChapters)
}
fun onViewerLoaded(viewer: Viewer?) {
mutableState.update {
it.copy(viewer = viewer)
}
}
/**
* Called every time a page changes on the reader. Used to mark the flag of chapters being
* read, update tracking services, enqueue downloaded chapter deletion, and updating the active chapter if this
@@ -1110,11 +1103,6 @@ class ReaderViewModel(
val bookmarked: Boolean = false,
val isLoadingAdjacentChapter: Boolean = false,
val currentPage: Int = -1,
/**
* Viewer used to display the pages (pager, webtoon, ...).
*/
val viewer: Viewer? = null,
val dialog: Dialog? = null,
val menuVisible: Boolean = false,
@IntRange(from = -100, to = 100) val brightnessOverlayValue: Int = 0,
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.reader.setting
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import eu.kanade.tachiyomi.ui.reader.ReaderViewModel
import eu.kanade.tachiyomi.ui.reader.viewer.Viewer
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -11,16 +12,12 @@ import kotlinx.coroutines.flow.stateIn
class ReaderSettingsViewModel(
readerState: StateFlow<ReaderViewModel.State>,
val viewerFlow: StateFlow<Viewer?>,
val onChangeReadingMode: (ReadingMode) -> Unit,
val onChangeOrientation: (ReaderOrientation) -> Unit,
val preferences: ReaderPreferences,
) : ViewModel() {
val viewerFlow = readerState
.map { it.viewer }
.distinctUntilChanged()
.stateIn(viewModelScope, SharingStarted.Lazily, null)
val mangaFlow = readerState
.map { it.manga }
.distinctUntilChanged()