Cleanup Preference.asHotFlow() (#9257)

* Drop duplicate initial call in Preference.asHotFlow

Preference.changes() always starts by returning the current value of
the preference, so asHotFlow calls block twice on the initial value.

Possible breaking change: As implemented, asHotFlow ran block(get())
before returning the flow. After this change, the first call to block
will run within the flow collection. This might cause concurrency
issues if the flow collection is late to execute.

* Inline Preference.asHotFlow

The Preference.changes().onEach().launchIn() pattern is used widely,
so the asHotFlow extension method is redundant.

(cherry picked from commit 35d381144d010be47566ee480c311c3d13952822)
This commit is contained in:
Two-Ai 2023-03-26 11:52:54 -04:00 committed by Jobobby04
parent 519abe90fc
commit 2815068a00
5 changed files with 27 additions and 34 deletions

View File

@ -36,7 +36,6 @@ import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.util.chapter.getNextUnread
import eu.kanade.tachiyomi.util.preference.asHotFlow
import eu.kanade.tachiyomi.util.removeCovers
import exh.favorites.FavoritesSyncHelper
import exh.md.utils.FollowStatus
@ -259,11 +258,13 @@ class LibraryScreenModel(
}
.launchIn(coroutineScope)
libraryPreferences.groupLibraryBy().asHotFlow {
mutableState.update { state ->
state.copy(groupType = it)
libraryPreferences.groupLibraryBy().changes()
.onEach {
mutableState.update { state ->
state.copy(groupType = it)
}
}
}.launchIn(coroutineScope)
.launchIn(coroutineScope)
// SY <--
}

View File

@ -10,9 +10,9 @@ import androidx.lifecycle.lifecycleScope
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.ReaderGeneralSettingsBinding
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.util.preference.asHotFlow
import eu.kanade.tachiyomi.util.preference.bindToPreference
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.injectLazy
/**
@ -38,8 +38,8 @@ class ReaderGeneralSettings @JvmOverloads constructor(context: Context, attrs: A
binding.backgroundColor.bindToIntPreference(readerPreferences.readerTheme(), R.array.reader_themes_values)
binding.showPageNumber.bindToPreference(readerPreferences.showPageNumber())
binding.fullscreen.bindToPreference(readerPreferences.fullscreen())
readerPreferences.fullscreen()
.asHotFlow {
readerPreferences.fullscreen().changes()
.onEach {
// If the preference is explicitly disabled, that means the setting was configured since there is a cutout
binding.cutoutShort.isVisible = it && ((context as ReaderActivity).hasCutout || !readerPreferences.cutoutShort().get())
binding.cutoutShort.bindToPreference(readerPreferences.cutoutShort())
@ -60,8 +60,8 @@ class ReaderGeneralSettings @JvmOverloads constructor(context: Context, attrs: A
// Hides landscapeVerticalSeekbar & leftVerticalSeekbar option when forceHorizontalSeekbar is enabled
binding.forceHorzSeekbar.bindToPreference(readerPreferences.forceHorizontalSeekbar())
readerPreferences.forceHorizontalSeekbar()
.asHotFlow {
readerPreferences.forceHorizontalSeekbar().changes()
.onEach {
binding.landscapeVerticalSeekbar.isGone = it
binding.leftVerticalSeekbar.isGone = it
}

View File

@ -13,9 +13,9 @@ import eu.kanade.tachiyomi.databinding.ReaderReadingModeSettingsBinding
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer
import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer
import eu.kanade.tachiyomi.util.preference.asHotFlow
import eu.kanade.tachiyomi.util.preference.bindToPreference
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.injectLazy
/**
@ -74,8 +74,8 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
binding.pagerPrefsGroup.navigatePan.bindToPreference(readerPreferences.navigateToPan())
binding.pagerPrefsGroup.pagerNav.bindToPreference(readerPreferences.navigationModePager())
readerPreferences.navigationModePager()
.asHotFlow {
readerPreferences.navigationModePager().changes()
.onEach {
val isTappingEnabled = it != 5
binding.pagerPrefsGroup.tappingInverted.isVisible = isTappingEnabled
binding.pagerPrefsGroup.navigatePan.isVisible = isTappingEnabled
@ -83,8 +83,8 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
.launchIn((context as ReaderActivity).lifecycleScope)
// Makes so that landscape zoom gets hidden away when image scale type is not fit screen
binding.pagerPrefsGroup.scaleType.bindToPreference(readerPreferences.imageScaleType(), 1)
readerPreferences.imageScaleType()
.asHotFlow { binding.pagerPrefsGroup.landscapeZoom.isVisible = it == 1 }
readerPreferences.imageScaleType().changes()
.onEach { binding.pagerPrefsGroup.landscapeZoom.isVisible = it == 1 }
.launchIn((context as ReaderActivity).lifecycleScope)
binding.pagerPrefsGroup.landscapeZoom.bindToPreference(readerPreferences.landscapeZoom())
@ -92,8 +92,8 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
binding.pagerPrefsGroup.cropBorders.bindToPreference(readerPreferences.cropBorders())
binding.pagerPrefsGroup.dualPageSplit.bindToPreference(readerPreferences.dualPageSplitPaged())
readerPreferences.dualPageSplitPaged()
.asHotFlow {
readerPreferences.dualPageSplitPaged().changes()
.onEach {
binding.pagerPrefsGroup.dualPageInvert.isVisible = it
if (it) {
binding.pagerPrefsGroup.dualPageRotateToFit.isChecked = false
@ -103,8 +103,8 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
binding.pagerPrefsGroup.dualPageInvert.bindToPreference(readerPreferences.dualPageInvertPaged())
binding.pagerPrefsGroup.dualPageRotateToFit.bindToPreference(readerPreferences.dualPageRotateToFit())
readerPreferences.dualPageRotateToFit()
.asHotFlow {
readerPreferences.dualPageRotateToFit().changes()
.onEach {
binding.pagerPrefsGroup.dualPageRotateToFitInvert.isVisible = it
if (it) {
binding.pagerPrefsGroup.dualPageSplit.isChecked = false
@ -131,16 +131,16 @@ class ReaderReadingModeSettings @JvmOverloads constructor(context: Context, attr
binding.webtoonPrefsGroup.tappingInverted.bindToPreference(readerPreferences.webtoonNavInverted(), ReaderPreferences.TappingInvertMode::class.java)
binding.webtoonPrefsGroup.webtoonNav.bindToPreference(readerPreferences.navigationModeWebtoon())
readerPreferences.navigationModeWebtoon()
.asHotFlow { binding.webtoonPrefsGroup.tappingInverted.isVisible = it != 5 }
readerPreferences.navigationModeWebtoon().changes()
.onEach { binding.webtoonPrefsGroup.tappingInverted.isVisible = it != 5 }
.launchIn((context as ReaderActivity).lifecycleScope)
binding.webtoonPrefsGroup.cropBordersWebtoon.bindToPreference(readerPreferences.cropBordersWebtoon())
binding.webtoonPrefsGroup.webtoonSidePadding.bindToIntPreference(readerPreferences.webtoonSidePadding(), R.array.webtoon_side_padding_values)
binding.webtoonPrefsGroup.dualPageSplit.bindToPreference(readerPreferences.dualPageSplitWebtoon())
// Makes it so that dual page invert gets hidden away when dual page split is turned off
readerPreferences.dualPageSplitWebtoon()
.asHotFlow { binding.webtoonPrefsGroup.dualPageInvert.isVisible = it }
readerPreferences.dualPageSplitWebtoon().changes()
.onEach { binding.webtoonPrefsGroup.dualPageInvert.isVisible = it }
.launchIn((context as ReaderActivity).lifecycleScope)
binding.webtoonPrefsGroup.dualPageInvert.bindToPreference(readerPreferences.dualPageInvertWebtoon())
binding.webtoonPrefsGroup.longStripSplit.bindToPreference(readerPreferences.longStripSplitWebtoon())

View File

@ -1,8 +1,6 @@
package eu.kanade.tachiyomi.util.preference
import android.widget.CompoundButton
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onEach
import tachiyomi.core.preference.Preference
/**
@ -13,12 +11,6 @@ fun CompoundButton.bindToPreference(pref: Preference<Boolean>) {
setOnCheckedChangeListener { _, isChecked -> pref.set(isChecked) }
}
fun <T> Preference<T>.asHotFlow(block: (T) -> Unit): Flow<T> {
block(get())
return changes()
.onEach { block(it) }
}
operator fun <T> Preference<Set<T>>.plusAssign(item: T) {
set(get() + item)
}

View File

@ -7,13 +7,13 @@ import androidx.core.view.inputmethod.EditorInfoCompat
import com.google.android.material.textfield.TextInputEditText
import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.preference.asHotFlow
import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -49,8 +49,8 @@ class TachiyomiTextInputEditText @JvmOverloads constructor(
* if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag.
*/
fun EditText.setIncognito(viewScope: CoroutineScope) {
Injekt.get<BasePreferences>().incognitoMode()
.asHotFlow {
Injekt.get<BasePreferences>().incognitoMode().changes()
.onEach {
imeOptions = if (it) {
imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING
} else {