diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5ae9d45ecb..3b4003d72d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -114,9 +114,11 @@ dependencies { implementation("com.google.firebase:firebase-core:17.3.0") - val lifecycleVersion = "2.1.0" + val lifecycleVersion = "2.2.0" implementation("androidx.lifecycle:lifecycle-extensions:$lifecycleVersion") implementation("androidx.lifecycle:lifecycle-common-java8:$lifecycleVersion") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion") + // ReactiveX implementation("io.reactivex:rxandroid:1.2.1") diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 9c84e839e4..bcd8c68624 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -61,51 +61,51 @@ class PreferencesHelper(val context: Context) { fun theme() = prefs.getInt(Keys.theme, 5) - fun rotation() = rxPrefs.getInteger(Keys.rotation, 1) + fun rotation() = flowPrefs.getInt(Keys.rotation, 1) - fun pageTransitions() = rxPrefs.getBoolean(Keys.enableTransitions, true) + fun pageTransitions() = flowPrefs.getBoolean(Keys.enableTransitions, true) - fun doubleTapAnimSpeed() = rxPrefs.getInteger(Keys.doubleTapAnimationSpeed, 500) + fun doubleTapAnimSpeed() = flowPrefs.getInt(Keys.doubleTapAnimationSpeed, 500) - fun showPageNumber() = rxPrefs.getBoolean(Keys.showPageNumber, true) + fun showPageNumber() = flowPrefs.getBoolean(Keys.showPageNumber, true) - fun trueColor() = rxPrefs.getBoolean(Keys.trueColor, false) + fun trueColor() = flowPrefs.getBoolean(Keys.trueColor, false) - fun fullscreen() = rxPrefs.getBoolean(Keys.fullscreen, true) + fun fullscreen() = flowPrefs.getBoolean(Keys.fullscreen, true) - fun keepScreenOn() = rxPrefs.getBoolean(Keys.keepScreenOn, true) + fun keepScreenOn() = flowPrefs.getBoolean(Keys.keepScreenOn, true) - fun customBrightness() = rxPrefs.getBoolean(Keys.customBrightness, false) + fun customBrightness() = flowPrefs.getBoolean(Keys.customBrightness, false) - fun customBrightnessValue() = rxPrefs.getInteger(Keys.customBrightnessValue, 0) + fun customBrightnessValue() = flowPrefs.getInt(Keys.customBrightnessValue, 0) - fun colorFilter() = rxPrefs.getBoolean(Keys.colorFilter, false) + fun colorFilter() = flowPrefs.getBoolean(Keys.colorFilter, false) - fun colorFilterValue() = rxPrefs.getInteger(Keys.colorFilterValue, 0) + fun colorFilterValue() = flowPrefs.getInt(Keys.colorFilterValue, 0) - fun colorFilterMode() = rxPrefs.getInteger(Keys.colorFilterMode, 0) + fun colorFilterMode() = flowPrefs.getInt(Keys.colorFilterMode, 0) fun defaultViewer() = prefs.getInt(Keys.defaultViewer, 1) - fun imageScaleType() = rxPrefs.getInteger(Keys.imageScaleType, 1) + fun imageScaleType() = flowPrefs.getInt(Keys.imageScaleType, 1) - fun zoomStart() = rxPrefs.getInteger(Keys.zoomStart, 1) + fun zoomStart() = flowPrefs.getInt(Keys.zoomStart, 1) - fun readerTheme() = rxPrefs.getInteger(Keys.readerTheme, 2) + fun readerTheme() = flowPrefs.getInt(Keys.readerTheme, 2) - fun cropBorders() = rxPrefs.getBoolean(Keys.cropBorders, false) + fun cropBorders() = flowPrefs.getBoolean(Keys.cropBorders, false) - fun cropBordersWebtoon() = rxPrefs.getBoolean(Keys.cropBordersWebtoon, false) + fun cropBordersWebtoon() = flowPrefs.getBoolean(Keys.cropBordersWebtoon, false) - fun webtoonSidePadding() = rxPrefs.getInteger(Keys.webtoonSidePadding, 0) + fun webtoonSidePadding() = flowPrefs.getInt(Keys.webtoonSidePadding, 0) - fun readWithTapping() = rxPrefs.getBoolean(Keys.readWithTapping, true) + fun readWithTapping() = flowPrefs.getBoolean(Keys.readWithTapping, true) - fun readWithLongTap() = rxPrefs.getBoolean(Keys.readWithLongTap, true) + fun readWithLongTap() = flowPrefs.getBoolean(Keys.readWithLongTap, true) - fun readWithVolumeKeys() = rxPrefs.getBoolean(Keys.readWithVolumeKeys, false) + fun readWithVolumeKeys() = flowPrefs.getBoolean(Keys.readWithVolumeKeys, false) - fun readWithVolumeKeysInverted() = rxPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false) + fun readWithVolumeKeysInverted() = flowPrefs.getBoolean(Keys.readWithVolumeKeysInverted, false) fun updateOnlyNonCompleted() = prefs.getBoolean(Keys.updateOnlyNonCompleted, false) @@ -257,7 +257,7 @@ class PreferencesHelper(val context: Context) { fun hideFiltersAtStart() = rxPrefs.getBoolean("hide_filters_at_start", false) - fun alwaysShowChapterTransition() = rxPrefs.getBoolean(Keys.alwaysShowChapterTransition, true) + fun alwaysShowChapterTransition() = flowPrefs.getBoolean(Keys.alwaysShowChapterTransition, true) fun deleteRemovedChapters() = flowPrefs.getInt(Keys.deleteRemovedChapters, 0) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt index d38ecabcc9..8a5e979ac7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.ui.base.activity import android.os.Bundle +import androidx.lifecycle.lifecycleScope import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.util.system.LocaleHelper @@ -8,6 +9,8 @@ import nucleus.view.NucleusAppCompatActivity abstract class BaseRxActivity

> : NucleusAppCompatActivity

() { + val scope = lifecycleScope + init { @Suppress("LeakingThis") LocaleHelper.updateConfiguration(this) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 8928c0e175..7ff2f4a8eb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -33,7 +33,6 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.base.activity.BaseRxActivity import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.AddToLibraryFirst import eu.kanade.tachiyomi.ui.reader.ReaderPresenter.SetAsCoverResult.Error @@ -46,7 +45,6 @@ import eu.kanade.tachiyomi.ui.reader.viewer.pager.L2RPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.pager.VerticalPagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer -import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.GLUtil import eu.kanade.tachiyomi.util.system.ThemeUtil @@ -72,17 +70,16 @@ import kotlinx.android.synthetic.main.reader_activity.* import kotlinx.android.synthetic.main.reader_chapters_sheet.* import kotlinx.coroutines.Job import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.drop +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.sample import me.zhanghai.android.systemuihelper.SystemUiHelper import nucleus.factory.RequiresPresenter -import rx.Observable -import rx.Subscription -import rx.android.schedulers.AndroidSchedulers -import rx.subscriptions.CompositeSubscription import timber.log.Timber import uy.kohesive.injekt.injectLazy import java.io.File import java.util.Locale -import java.util.concurrent.TimeUnit import kotlin.math.abs /** @@ -222,7 +219,6 @@ class ReaderActivity : BaseRxActivity(), viewer?.destroy() chapters_bottom_sheet.adapter = null viewer = null - config?.destroy() config = null bottomSheet?.dismiss() bottomSheet = null @@ -724,67 +720,52 @@ class ReaderActivity : BaseRxActivity(), */ private inner class ReaderConfig { - /** - * List of subscriptions to keep while the reader is alive. - */ - private val subscriptions = CompositeSubscription() - - /** - * Custom brightness subscription. - */ - private var customBrightnessSubscription: Subscription? = null - - /** - * Custom color filter subscription. - */ - private var customFilterColorSubscription: Subscription? = null - var showNewChapter = false /** * Initializes the reader subscriptions. */ init { - val sharedRotation = preferences.rotation().asObservable().share() - val initialRotation = sharedRotation.take(1) - val rotationUpdates = sharedRotation.skip(1) - .delay(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) + setOrientation(preferences.rotation().get()) + preferences.rotation().asFlow() + .drop(1) + .onEach { + delay(250) + setOrientation(it) + } + .launchIn(scope) - subscriptions += Observable.merge(initialRotation, rotationUpdates) - .subscribe { setOrientation(it) } + preferences.showPageNumber().asFlow() + .onEach { setPageNumberVisibility(it) } + .launchIn(scope) - subscriptions += preferences.showPageNumber().asObservable() - .subscribe { setPageNumberVisibility(it) } + preferences.trueColor().asFlow() + .onEach { setTrueColor(it) } + .launchIn(scope) - subscriptions += preferences.trueColor().asObservable() - .subscribe { setTrueColor(it) } + preferences.fullscreen().asFlow() + .onEach { setFullscreen(it) } + .launchIn(scope) - subscriptions += preferences.fullscreen().asObservable() - .subscribe { setFullscreen(it) } + preferences.keepScreenOn().asFlow() + .onEach { setKeepScreenOn(it) } + .launchIn(scope) - subscriptions += preferences.keepScreenOn().asObservable() - .subscribe { setKeepScreenOn(it) } + preferences.customBrightness().asFlow() + .onEach { setCustomBrightness(it) } + .launchIn(scope) - subscriptions += preferences.customBrightness().asObservable() - .subscribe { setCustomBrightness(it) } + preferences.colorFilter().asFlow() + .onEach { setColorFilter(it) } + .launchIn(scope) - subscriptions += preferences.colorFilter().asObservable() - .subscribe { setColorFilter(it) } + preferences.colorFilterMode().asFlow() + .onEach { setColorFilter(preferences.colorFilter().get()) } + .launchIn(scope) - subscriptions += preferences.colorFilterMode().asObservable() - .subscribe { setColorFilter(preferences.colorFilter().getOrDefault()) } - - subscriptions += preferences.alwaysShowChapterTransition().asObservable() - .subscribe { showNewChapter = it } - } - - /** - * Called when the reader is being destroyed. It cleans up all the subscriptions. - */ - fun destroy() { - subscriptions.unsubscribe() - customBrightnessSubscription = null - customFilterColorSubscription = null + preferences.alwaysShowChapterTransition().asFlow() + .onEach { showNewChapter = it } + .launchIn(scope) } /** @@ -861,13 +842,11 @@ class ReaderActivity : BaseRxActivity(), */ private fun setCustomBrightness(enabled: Boolean) { if (enabled) { - customBrightnessSubscription = preferences.customBrightnessValue().asObservable() - .sample(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - .subscribe { setCustomBrightnessValue(it) } - - subscriptions.add(customBrightnessSubscription) + preferences.customBrightnessValue().asFlow() + .sample(100) + .onEach { setCustomBrightnessValue(it) } + .launchIn(scope) } else { - customBrightnessSubscription?.let { subscriptions.remove(it) } setCustomBrightnessValue(0) } } @@ -877,14 +856,12 @@ class ReaderActivity : BaseRxActivity(), */ private fun setColorFilter(enabled: Boolean) { if (enabled) { - customFilterColorSubscription = preferences.colorFilterValue().asObservable() - .sample(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - .subscribe { setColorFilterValue(it) } - - subscriptions.add(customFilterColorSubscription) + preferences.colorFilterValue().asFlow() + .sample(100) + .onEach { setColorFilterValue(it) } + .launchIn(scope) } else { - customFilterColorSubscription?.let { subscriptions.remove(it) } - color_overlay.visibility = View.GONE + color_overlay.gone() } } @@ -910,11 +887,11 @@ class ReaderActivity : BaseRxActivity(), // Set black overlay visibility. if (value < 0) { - brightness_overlay.visibility = View.VISIBLE + brightness_overlay.visible() val alpha = (abs(value) * 2.56).toInt() brightness_overlay.setBackgroundColor(Color.argb(alpha, 0, 0, 0)) } else { - brightness_overlay.visibility = View.GONE + brightness_overlay.gone() } } @@ -922,8 +899,8 @@ class ReaderActivity : BaseRxActivity(), * Sets the color filter [value]. */ private fun setColorFilterValue(value: Int) { - color_overlay.visibility = View.VISIBLE - color_overlay.setFilterColor(value, preferences.colorFilterMode().getOrDefault()) + color_overlay.visible() + color_overlay.setFilterColor(value, preferences.colorFilterMode().get()) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt index 4590db11c2..32b924a4a7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt @@ -10,48 +10,33 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.system.hasSideNavBar +import eu.kanade.tachiyomi.util.system.isInNightMode import eu.kanade.tachiyomi.util.view.expand +import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.setBottomEdge import eu.kanade.tachiyomi.util.view.setEdgeToEdge +import eu.kanade.tachiyomi.util.view.visible import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import kotlinx.android.synthetic.main.reader_color_filter.* import kotlinx.android.synthetic.main.reader_color_filter_sheet.* -import rx.Subscription -import rx.android.schedulers.AndroidSchedulers -import rx.subscriptions.CompositeSubscription +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.sample import uy.kohesive.injekt.injectLazy -import java.util.concurrent.TimeUnit import kotlin.math.abs /** * Color filter sheet to toggle custom filter and brightness overlay. */ -class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog +class ReaderColorFilterSheet(private val activity: ReaderActivity) : BottomSheetDialog (activity, R.style.BottomSheetDialogTheme) { private val preferences by injectLazy() private var sheetBehavior: BottomSheetBehavior<*>? = null - /** - * Subscriptions used for this dialog - */ - private val subscriptions = CompositeSubscription() - - /** - * Subscription used for custom brightness overlay - */ - private var customBrightnessSubscription: Subscription? = null - - /** - * Subscription used for color filter overlay - */ - private var customFilterColorSubscription: Subscription? = null - init { val view = activity.layoutInflater.inflate(R.layout.reader_color_filter_sheet, null) setContentView(view) @@ -59,26 +44,28 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog setEdgeToEdge(activity, view, 0) window?.navigationBarColor = Color.TRANSPARENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && - preferences.readerTheme().getOrDefault() == 0 && + !context.isInNightMode() && !activity.window.decorView.rootWindowInsets.hasSideNavBar()) window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR setBottomEdge(brightness_seekbar, activity) sheetBehavior = BottomSheetBehavior.from(view.parent as ViewGroup) - // Initialize subscriptions. - subscriptions += preferences.colorFilter().asObservable() - .subscribe { setColorFilter(it, view) } + preferences.colorFilter().asFlow() + .onEach { setColorFilter(it, view) } + .launchIn(activity.scope) - subscriptions += preferences.colorFilterMode().asObservable() - .subscribe { setColorFilter(preferences.colorFilter().getOrDefault(), view) } + preferences.colorFilterMode().asFlow() + .onEach { setColorFilter(preferences.colorFilter().get(), view) } + .launchIn(activity.scope) - subscriptions += preferences.customBrightness().asObservable() - .subscribe { setCustomBrightness(it, view) } + preferences.customBrightness().asFlow() + .onEach { setCustomBrightness(it, view) } + .launchIn(activity.scope) // Get color and update values - val color = preferences.colorFilterValue().getOrDefault() - val brightness = preferences.customBrightnessValue().getOrDefault() + val color = preferences.colorFilterValue().get() + val brightness = preferences.customBrightnessValue().get() val argb = setValues(color, view) @@ -93,26 +80,20 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog seekbar_color_filter_blue.progress = argb[3] // Set listeners - switch_color_filter.isChecked = preferences.colorFilter().getOrDefault() + switch_color_filter.isChecked = preferences.colorFilter().get() switch_color_filter.setOnCheckedChangeListener { _, isChecked -> preferences.colorFilter().set(isChecked) } - custom_brightness.isChecked = preferences.customBrightness().getOrDefault() + custom_brightness.isChecked = preferences.customBrightness().get() custom_brightness.setOnCheckedChangeListener { _, isChecked -> preferences.customBrightness().set(isChecked) } - /*color_filter_mode.setOnClickListener { - val popupMenu = PopupMenu(context, color_filter_mode) - - popupMenu.menuInflater.inflate(R.menu.download_single, popupMenu.menu) - popupMenu.show() - }*/ color_filter_mode.onItemSelectedListener = IgnoreFirstSpinnerListener { position -> preferences.colorFilterMode().set(position) } - color_filter_mode.setSelection(preferences.colorFilterMode().getOrDefault(), false) + color_filter_mode.setSelection(preferences.colorFilterMode().get(), false) seekbar_color_filter_alpha.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { @@ -161,13 +142,6 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog sheetBehavior?.expand() } - override fun onDetachedFromWindow() { - super.onDetachedFromWindow() - subscriptions.unsubscribe() - customBrightnessSubscription = null - customFilterColorSubscription = null - } - /** * Set enabled status of seekBars belonging to color filter * @param enabled determines if seekBar gets enabled @@ -201,15 +175,11 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog val blue = getBlueFromColor(color) // Initialize values - with(view) { - txt_color_filter_alpha_value.text = alpha.toString() + txt_color_filter_alpha_value.text = alpha.toString() + txt_color_filter_red_value.text = red.toString() + txt_color_filter_green_value.text = green.toString() + txt_color_filter_blue_value.text = blue.toString() - txt_color_filter_red_value.text = red.toString() - - txt_color_filter_green_value.text = green.toString() - - txt_color_filter_blue_value.text = blue.toString() - } return arrayOf(alpha, red, green, blue) } @@ -220,13 +190,11 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog */ private fun setCustomBrightness(enabled: Boolean, view: View) { if (enabled) { - customBrightnessSubscription = preferences.customBrightnessValue().asObservable() - .sample(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - .subscribe { setCustomBrightnessValue(it, view) } - - subscriptions.add(customBrightnessSubscription) + preferences.customBrightnessValue().asFlow() + .sample(100) + .onEach { setCustomBrightnessValue(it, view) } + .launchIn(activity.scope) } else { - customBrightnessSubscription?.let { subscriptions.remove(it) } setCustomBrightnessValue(0, view, true) } setCustomBrightnessSeekBar(enabled, view) @@ -241,15 +209,16 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog private fun setCustomBrightnessValue(value: Int, view: View, isDisabled: Boolean = false) = with(view) { // Set black overlay visibility. if (value < 0) { - brightness_overlay.visibility = View.VISIBLE + brightness_overlay.visible() val alpha = (abs(value) * 2.56).toInt() brightness_overlay.setBackgroundColor(Color.argb(alpha, 0, 0, 0)) } else { - brightness_overlay.visibility = View.GONE + brightness_overlay.gone() } - if (!isDisabled) + if (!isDisabled) { txt_brightness_seekbar_value.text = value.toString() + } } /** @@ -259,14 +228,12 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog */ private fun setColorFilter(enabled: Boolean, view: View) { if (enabled) { - customFilterColorSubscription = preferences.colorFilterValue().asObservable() - .sample(100, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - .subscribe { setColorFilterValue(it, view) } - - subscriptions.add(customFilterColorSubscription) + preferences.colorFilterValue().asFlow() + .sample(100) + .onEach { setColorFilterValue(it, view) } + .launchIn(activity.scope) } else { - customFilterColorSubscription?.let { subscriptions.remove(it) } - color_overlay.visibility = View.GONE + color_overlay.gone() } setColorFilterSeekBar(enabled, view) } @@ -277,8 +244,8 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog * @param view view of the dialog */ private fun setColorFilterValue(@ColorInt color: Int, view: View) = with(view) { - color_overlay.visibility = View.VISIBLE - color_overlay.setFilterColor(color, preferences.colorFilterMode().getOrDefault()) + color_overlay.visible() + color_overlay.setFilterColor(color, preferences.colorFilterMode().get()) setValues(color, view) } @@ -289,7 +256,7 @@ class ReaderColorFilterSheet(activity: ReaderActivity) : BottomSheetDialog * @param bitShift amounts of bits that gets shifted to receive value */ fun setColorValue(color: Int, mask: Long, bitShift: Int) { - val currentColor = preferences.colorFilterValue().getOrDefault() + val currentColor = preferences.colorFilterValue().get() val updatedColor = (color shl bitShift) or (currentColor and mask.inv().toInt()) preferences.colorFilterValue().set(updatedColor) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt index f855502170..5c8ebd4423 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPageSheet.kt @@ -8,16 +8,13 @@ import android.view.ViewGroup import com.afollestad.materialdialogs.MaterialDialog import com.google.android.material.bottomsheet.BottomSheetDialog import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.system.hasSideNavBar +import eu.kanade.tachiyomi.util.system.isInNightMode import eu.kanade.tachiyomi.util.view.setBottomEdge import eu.kanade.tachiyomi.util.view.setEdgeToEdge import kotlinx.android.synthetic.main.reader_page_sheet.* -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get /** * Sheet to show when a page is long clicked. @@ -37,7 +34,7 @@ class ReaderPageSheet( setEdgeToEdge(activity, view) window?.navigationBarColor = Color.TRANSPARENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && - Injekt.get().readerTheme().getOrDefault() == 0 && + !context.isInNightMode() && !activity.window.decorView.rootWindowInsets.hasSideNavBar()) window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt index 4a3851a6e3..17a800443a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsSheet.kt @@ -9,16 +9,16 @@ import android.view.ViewGroup import android.widget.CompoundButton import android.widget.Spinner import androidx.annotation.ArrayRes -import com.f2prateek.rx.preferences.Preference import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog +import com.tfcporciuncula.flow.Preference import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerViewer import eu.kanade.tachiyomi.ui.reader.viewer.webtoon.WebtoonViewer import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.hasSideNavBar +import eu.kanade.tachiyomi.util.system.isInNightMode import eu.kanade.tachiyomi.util.view.gone import eu.kanade.tachiyomi.util.view.setBottomEdge import eu.kanade.tachiyomi.util.view.setEdgeToEdge @@ -54,7 +54,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : ) window?.navigationBarColor = Color.TRANSPARENT if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && - preferences.readerTheme().getOrDefault() == 0 && + !context.isInNightMode() && !activity.window.decorView.rootWindowInsets.hasSideNavBar() ) { window?.decorView?.systemUiVisibility = View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR @@ -156,7 +156,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : * Binds a checkbox or switch view with a boolean preference. */ private fun CompoundButton.bindToPreference(pref: Preference) { - isChecked = pref.getOrDefault() + isChecked = pref.get() setOnCheckedChangeListener { _, isChecked -> pref.set(isChecked) } } @@ -170,7 +170,7 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : onItemSelectedListener = IgnoreFirstSpinnerListener { position -> pref.set(position + offset) } - setSelection(pref.getOrDefault() - offset, false) + setSelection(pref.get() - offset, false) } /** @@ -181,8 +181,8 @@ class ReaderSettingsSheet(private val activity: ReaderActivity) : private fun Spinner.bindToIntPreference(pref: Preference, @ArrayRes intValuesResource: Int) { val intValues = resources.getStringArray(intValuesResource).map { it.toIntOrNull() } onItemSelectedListener = IgnoreFirstSpinnerListener { position -> - pref.set(intValues[position]) + pref.set(intValues[position] ?: 0) } - setSelection(intValues.indexOf(pref.getOrDefault()), false) + setSelection(intValues.indexOf(pref.get()), false) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt index 535fae9a71..c5e7d32c68 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.reader.loader import android.graphics.BitmapFactory import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter @@ -221,7 +220,7 @@ class HttpPageLoader( Observable.just(page) } }.doOnNext { - val readerTheme = preferences.readerTheme().getOrDefault() + val readerTheme = preferences.readerTheme().get() if (readerTheme >= 2) { val stream = chapterCache.getImageFile(imageUrl).inputStream() val image = BitmapFactory.decodeStream(stream) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt new file mode 100644 index 0000000000..fab2958314 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt @@ -0,0 +1,58 @@ +package eu.kanade.tachiyomi.ui.reader.viewer + +import com.tfcporciuncula.flow.Preference +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach + +/** + * Common configuration for all viewers. + */ +abstract class ViewerConfig(preferences: PreferencesHelper) { + + private val scope = CoroutineScope(Job() + Dispatchers.Main) + + var imagePropertyChangedListener: (() -> Unit)? = null + + var tappingEnabled = true + var longTapEnabled = true + var doubleTapAnimDuration = 500 + var volumeKeysEnabled = false + var volumeKeysInverted = false + var alwaysShowChapterTransition = true + + init { + preferences.readWithTapping() + .register({ tappingEnabled = it }) + + preferences.readWithLongTap() + .register({ longTapEnabled = it }) + + preferences.doubleTapAnimSpeed() + .register({ doubleTapAnimDuration = it }) + + preferences.readWithVolumeKeys() + .register({ volumeKeysEnabled = it }) + + preferences.readWithVolumeKeysInverted() + .register({ volumeKeysInverted = it }) + + preferences.alwaysShowChapterTransition() + .register({ alwaysShowChapterTransition = it }) + } + + fun Preference.register( + valueAssignment: (T) -> Unit, + onChanged: (T) -> Unit = {} + ) { + asFlow() + .onEach { + valueAssignment(it) + onChanged(it) + } + .launchIn(scope) + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt index 2f303e15e8..c6ac8ad7ce 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt @@ -1,32 +1,15 @@ package eu.kanade.tachiyomi.ui.reader.viewer.pager -import com.f2prateek.rx.preferences.Preference import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.util.lang.addTo -import rx.subscriptions.CompositeSubscription +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get /** * Configuration used by pager viewers. */ -class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelper = Injekt.get()) { - - private val subscriptions = CompositeSubscription() - - var imagePropertyChangedListener: (() -> Unit)? = null - - var tappingEnabled = true - private set - - var longTapEnabled = true - private set - - var volumeKeysEnabled = false - private set - - var volumeKeysInverted = false - private set +class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelper = Injekt.get()) : + ViewerConfig(preferences) { var usePageTransitions = false private set @@ -40,22 +23,10 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe var imageCropBorders = false private set - var doubleTapAnimDuration = 500 - private set - var readerTheme = 0 private set - var alwaysShowChapterTransition = true - private set - init { - preferences.readWithTapping() - .register({ tappingEnabled = it }) - - preferences.readWithLongTap() - .register({ longTapEnabled = it }) - preferences.pageTransitions() .register({ usePageTransitions = it }) @@ -68,37 +39,8 @@ class PagerConfig(private val viewer: PagerViewer, preferences: PreferencesHelpe preferences.cropBorders() .register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() }) - preferences.doubleTapAnimSpeed() - .register({ doubleTapAnimDuration = it }) - - preferences.readWithVolumeKeys() - .register({ volumeKeysEnabled = it }) - - preferences.readWithVolumeKeysInverted() - .register({ volumeKeysInverted = it }) - preferences.readerTheme() - .register({ readerTheme = it }, { imagePropertyChangedListener?.invoke() }) - - preferences.alwaysShowChapterTransition() - .register({ alwaysShowChapterTransition = it }) - } - - fun unsubscribe() { - subscriptions.unsubscribe() - } - - private fun Preference.register( - valueAssignment: (T) -> Unit, - onChanged: (T) -> Unit = {} - ) { - asObservable() - .doOnNext(valueAssignment) - .skip(1) - .distinctUntilChanged() - .doOnNext(onChanged) - .subscribe() - .addTo(subscriptions) + .register({ readerTheme = it }, { imagePropertyChangedListener?.invoke() }) } private fun zoomTypeFromPreference(value: Int) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index a026fc80cd..651e6dd42e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -32,7 +32,6 @@ import com.github.chrisbanes.photoview.PhotoView import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.viewer.ReaderProgressBar @@ -304,7 +303,7 @@ class PagerPageHolder( val preferences by injectLazy() ImageUtil.autoSetBackground(BitmapFactory.decodeByteArray( bytesArray, 0, bytesArray.size - ), preferences.readerTheme().getOrDefault() == 2, context) + ), preferences.readerTheme().get() == 2, context) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt index f4b822958a..6f108b892c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt @@ -1,91 +1,26 @@ package eu.kanade.tachiyomi.ui.reader.viewer.webtoon -import com.f2prateek.rx.preferences.Preference import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.util.lang.addTo -import rx.subscriptions.CompositeSubscription +import eu.kanade.tachiyomi.ui.reader.viewer.ViewerConfig import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get /** * Configuration used by webtoon viewers. */ -class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) { - - private val subscriptions = CompositeSubscription() - - var imagePropertyChangedListener: (() -> Unit)? = null - - var tappingEnabled = true - private set - - var longTapEnabled = true - private set - - var volumeKeysEnabled = false - private set - - var volumeKeysInverted = false - private set +class WebtoonConfig(preferences: PreferencesHelper = Injekt.get()) : ViewerConfig(preferences) { var imageCropBorders = false private set - var doubleTapAnimDuration = 500 - private set - - var alwaysShowChapterTransition = true - private set - var sidePadding = 0 private set - var readerTheme = 0 - private set - init { - preferences.readWithTapping() - .register({ tappingEnabled = it }) - - preferences.readWithLongTap() - .register({ longTapEnabled = it }) - preferences.cropBordersWebtoon() .register({ imageCropBorders = it }, { imagePropertyChangedListener?.invoke() }) - preferences.doubleTapAnimSpeed() - .register({ doubleTapAnimDuration = it }) - - preferences.readWithVolumeKeys() - .register({ volumeKeysEnabled = it }) - - preferences.readWithVolumeKeysInverted() - .register({ volumeKeysInverted = it }) - - preferences.alwaysShowChapterTransition() - .register({ alwaysShowChapterTransition = it }) - preferences.webtoonSidePadding() .register({ sidePadding = it }, { imagePropertyChangedListener?.invoke() }) - - preferences.readerTheme() - .register({ readerTheme = it }, { imagePropertyChangedListener?.invoke() }) - } - - fun unsubscribe() { - subscriptions.unsubscribe() - } - - private fun Preference.register( - valueAssignment: (T) -> Unit, - onChanged: (T) -> Unit = {} - ) { - asObservable() - .doOnNext(valueAssignment) - .skip(1) - .distinctUntilChanged() - .doOnNext(onChanged) - .subscribe() - .addTo(subscriptions) } }