From 35d381144d010be47566ee480c311c3d13952822 Mon Sep 17 00:00:00 2001
From: Two-Ai <81279822+Two-Ai@users.noreply.github.com>
Date: Sun, 26 Mar 2023 11:52:54 -0400
Subject: [PATCH] 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.
---
 .../reader/setting/ReaderGeneralSettings.kt   |  6 ++---
 .../setting/ReaderReadingModeSettings.kt      | 26 +++++++++----------
 .../util/preference/PreferenceExtensions.kt   |  8 ------
 .../widget/TachiyomiTextInputEditText.kt      |  6 ++---
 4 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderGeneralSettings.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderGeneralSettings.kt
index 742c1b8f2..50beac220 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderGeneralSettings.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderGeneralSettings.kt
@@ -9,9 +9,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
 
 /**
@@ -37,8 +37,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())
diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderReadingModeSettings.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderReadingModeSettings.kt
index da9eb941f..02bb3321d 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderReadingModeSettings.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderReadingModeSettings.kt
@@ -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
@@ -124,16 +124,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())
diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt
index d8cf1a61f..7009635c6 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt
@@ -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)
 }
diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt
index bf77d38fd..a571b68fa 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt
@@ -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 {