Reader bottom bar actions configurable
This commit is contained in:
@@ -141,6 +141,11 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
val isReaderOptimizationEnabled: Boolean
|
val isReaderOptimizationEnabled: Boolean
|
||||||
get() = prefs.getBoolean(KEY_READER_OPTIMIZE, false)
|
get() = prefs.getBoolean(KEY_READER_OPTIMIZE, false)
|
||||||
|
|
||||||
|
val readerControls: Set<ReaderControl>
|
||||||
|
get() = prefs.getStringSet(KEY_READER_CONTROLS, null)?.mapNotNullTo(EnumSet.noneOf(ReaderControl::class.java)) {
|
||||||
|
ReaderControl.entries.find(it)
|
||||||
|
} ?: EnumSet.allOf(ReaderControl::class.java)
|
||||||
|
|
||||||
val isOfflineCheckDisabled: Boolean
|
val isOfflineCheckDisabled: Boolean
|
||||||
get() = prefs.getBoolean(KEY_OFFLINE_DISABLED, false)
|
get() = prefs.getBoolean(KEY_OFFLINE_DISABLED, false)
|
||||||
|
|
||||||
@@ -631,6 +636,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) {
|
|||||||
const val KEY_NOTIFICATIONS_LIGHT = "notifications_light"
|
const val KEY_NOTIFICATIONS_LIGHT = "notifications_light"
|
||||||
const val KEY_NOTIFICATIONS_INFO = "tracker_notifications_info"
|
const val KEY_NOTIFICATIONS_INFO = "tracker_notifications_info"
|
||||||
const val KEY_READER_ANIMATION = "reader_animation2"
|
const val KEY_READER_ANIMATION = "reader_animation2"
|
||||||
|
const val KEY_READER_CONTROLS = "reader_controls"
|
||||||
const val KEY_READER_MODE = "reader_mode"
|
const val KEY_READER_MODE = "reader_mode"
|
||||||
const val KEY_READER_MODE_DETECT = "reader_mode_detect"
|
const val KEY_READER_MODE_DETECT = "reader_mode_detect"
|
||||||
const val KEY_READER_CROP = "reader_crop"
|
const val KEY_READER_CROP = "reader_crop"
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.koitharu.kotatsu.core.prefs
|
||||||
|
|
||||||
|
enum class ReaderControl {
|
||||||
|
|
||||||
|
PREV_CHAPTER, NEXT_CHAPTER, SLIDER, PAGES_SHEET
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.util.ext
|
|||||||
|
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
|
import androidx.preference.MultiSelectListPreference
|
||||||
|
|
||||||
fun ListPreference.setDefaultValueCompat(defaultValue: String) {
|
fun ListPreference.setDefaultValueCompat(defaultValue: String) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
@@ -9,6 +10,10 @@ fun ListPreference.setDefaultValueCompat(defaultValue: String) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun MultiSelectListPreference.setDefaultValueCompat(defaultValue: Set<String>) {
|
||||||
|
setDefaultValue(defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
fun <E : Enum<E>> SharedPreferences.getEnumValue(key: String, enumClass: Class<E>): E? {
|
fun <E : Enum<E>> SharedPreferences.getEnumValue(key: String, enumClass: Class<E>): E? {
|
||||||
val stringValue = getString(key, null) ?: return null
|
val stringValue = getString(key, null) ?: return null
|
||||||
return enumClass.enumConstants?.find {
|
return enumClass.enumConstants?.find {
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ import org.koitharu.kotatsu.core.exceptions.resolve.DialogErrorObserver
|
|||||||
import org.koitharu.kotatsu.core.nav.AppRouter
|
import org.koitharu.kotatsu.core.nav.AppRouter
|
||||||
import org.koitharu.kotatsu.core.nav.router
|
import org.koitharu.kotatsu.core.nav.router
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
|
import org.koitharu.kotatsu.core.prefs.ReaderControl
|
||||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||||
import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity
|
import org.koitharu.kotatsu.core.ui.BaseFullscreenActivity
|
||||||
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||||
@@ -145,6 +146,7 @@ class ReaderActivity :
|
|||||||
viewModel.content.observe(this) {
|
viewModel.content.observe(this) {
|
||||||
onLoadingStateChanged(viewModel.isLoading.value)
|
onLoadingStateChanged(viewModel.isLoading.value)
|
||||||
}
|
}
|
||||||
|
viewModel.readerControls.observe(this, ::onReaderControlsChanged)
|
||||||
viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn)
|
viewModel.isKeepScreenOnEnabled.observe(this, this::setKeepScreenOn)
|
||||||
viewModel.isInfoBarTransparent.observe(this) { viewBinding.infoBar.drawBackground = !it }
|
viewModel.isInfoBarTransparent.observe(this) { viewBinding.infoBar.drawBackground = !it }
|
||||||
viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged)
|
viewModel.isInfoBarEnabled.observe(this, ::onReaderBarChanged)
|
||||||
@@ -297,6 +299,13 @@ class ReaderActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onReaderControlsChanged(controls: Set<ReaderControl>) = with(viewBinding) {
|
||||||
|
buttonPrev.isVisible = ReaderControl.PREV_CHAPTER in controls
|
||||||
|
buttonNext.isVisible = ReaderControl.NEXT_CHAPTER in controls
|
||||||
|
slider.isVisible = ReaderControl.SLIDER in controls
|
||||||
|
toolbarBottom.invalidateMenu()
|
||||||
|
}
|
||||||
|
|
||||||
private fun setUiIsVisible(isUiVisible: Boolean) {
|
private fun setUiIsVisible(isUiVisible: Boolean) {
|
||||||
if (viewBinding.appbarTop.isVisible != isUiVisible) {
|
if (viewBinding.appbarTop.isVisible != isUiVisible) {
|
||||||
if (isAnimationsEnabled) {
|
if (isAnimationsEnabled) {
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.core.view.MenuProvider
|
|||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.nav.router
|
import org.koitharu.kotatsu.core.nav.router
|
||||||
|
import org.koitharu.kotatsu.core.prefs.ReaderControl
|
||||||
|
|
||||||
class ReaderMenuBottomProvider(
|
class ReaderMenuBottomProvider(
|
||||||
private val activity: FragmentActivity,
|
private val activity: FragmentActivity,
|
||||||
@@ -20,10 +21,11 @@ class ReaderMenuBottomProvider(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onPrepareMenu(menu: Menu) {
|
override fun onPrepareMenu(menu: Menu) {
|
||||||
val hasPages = viewModel.content.value.pages.isNotEmpty()
|
val isPagesSheetEnabled = viewModel.content.value.pages.isNotEmpty() &&
|
||||||
|
ReaderControl.PAGES_SHEET in viewModel.readerControls.value
|
||||||
menu.findItem(R.id.action_pages_thumbs).run {
|
menu.findItem(R.id.action_pages_thumbs).run {
|
||||||
isVisible = hasPages
|
isVisible = isPagesSheetEnabled
|
||||||
if (hasPages) {
|
if (isPagesSheetEnabled) {
|
||||||
setIcon(if (viewModel.isPagesSheetEnabled.value) R.drawable.ic_grid else R.drawable.ic_list)
|
setIcon(if (viewModel.isPagesSheetEnabled.value) R.drawable.ic_grid else R.drawable.ic_list)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,12 @@ class ReaderViewModel @Inject constructor(
|
|||||||
valueProducer = { isReaderBarEnabled },
|
valueProducer = { isReaderBarEnabled },
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val readerControls = settings.observeAsStateFlow(
|
||||||
|
scope = viewModelScope + Dispatchers.Default,
|
||||||
|
key = AppSettings.KEY_READER_CONTROLS,
|
||||||
|
valueProducer = { readerControls },
|
||||||
|
)
|
||||||
|
|
||||||
val isInfoBarTransparent = settings.observeAsStateFlow(
|
val isInfoBarTransparent = settings.observeAsStateFlow(
|
||||||
scope = viewModelScope + Dispatchers.Default,
|
scope = viewModelScope + Dispatchers.Default,
|
||||||
key = AppSettings.KEY_READER_BAR_TRANSPARENT,
|
key = AppSettings.KEY_READER_BAR_TRANSPARENT,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.core.nav.router
|
|||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.core.prefs.ReaderAnimation
|
import org.koitharu.kotatsu.core.prefs.ReaderAnimation
|
||||||
import org.koitharu.kotatsu.core.prefs.ReaderBackground
|
import org.koitharu.kotatsu.core.prefs.ReaderBackground
|
||||||
|
import org.koitharu.kotatsu.core.prefs.ReaderControl
|
||||||
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
import org.koitharu.kotatsu.core.prefs.ReaderMode
|
||||||
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
import org.koitharu.kotatsu.core.ui.BasePreferenceFragment
|
||||||
import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat
|
import org.koitharu.kotatsu.core.util.ext.setDefaultValueCompat
|
||||||
@@ -30,12 +31,7 @@ class ReaderSettingsFragment :
|
|||||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||||
addPreferencesFromResource(R.xml.pref_reader)
|
addPreferencesFromResource(R.xml.pref_reader)
|
||||||
findPreference<ListPreference>(AppSettings.KEY_READER_MODE)?.run {
|
findPreference<ListPreference>(AppSettings.KEY_READER_MODE)?.run {
|
||||||
entryValues = arrayOf(
|
entryValues = ReaderMode.entries.names()
|
||||||
ReaderMode.STANDARD.name,
|
|
||||||
ReaderMode.REVERSED.name,
|
|
||||||
ReaderMode.VERTICAL.name,
|
|
||||||
ReaderMode.WEBTOON.name,
|
|
||||||
)
|
|
||||||
setDefaultValueCompat(ReaderMode.STANDARD.name)
|
setDefaultValueCompat(ReaderMode.STANDARD.name)
|
||||||
}
|
}
|
||||||
findPreference<ListPreference>(AppSettings.KEY_READER_ORIENTATION)?.run {
|
findPreference<ListPreference>(AppSettings.KEY_READER_ORIENTATION)?.run {
|
||||||
@@ -47,6 +43,11 @@ class ReaderSettingsFragment :
|
|||||||
)
|
)
|
||||||
setDefaultValueCompat(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED.toString())
|
setDefaultValueCompat(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED.toString())
|
||||||
}
|
}
|
||||||
|
findPreference<MultiSelectListPreference>(AppSettings.KEY_READER_CONTROLS)?.run {
|
||||||
|
entryValues = ReaderControl.entries.names()
|
||||||
|
setDefaultValueCompat(ReaderControl.entries.names().toSet())
|
||||||
|
summaryProvider = MultiSummaryProvider(R.string.none)
|
||||||
|
}
|
||||||
findPreference<ListPreference>(AppSettings.KEY_READER_BACKGROUND)?.run {
|
findPreference<ListPreference>(AppSettings.KEY_READER_BACKGROUND)?.run {
|
||||||
entryValues = ReaderBackground.entries.names()
|
entryValues = ReaderBackground.entries.names()
|
||||||
setDefaultValueCompat(ReaderBackground.DEFAULT.name)
|
setDefaultValueCompat(ReaderBackground.DEFAULT.name)
|
||||||
|
|||||||
@@ -69,20 +69,19 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
tools:menu="@menu/opt_reader_bottom">
|
tools:menu="@menu/opt_reader_bottom">
|
||||||
|
|
||||||
<RelativeLayout
|
<LinearLayout
|
||||||
android:id="@+id/layout_slider"
|
android:id="@+id/layout_slider"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginEnd="2dp">
|
android:layout_marginEnd="2dp"
|
||||||
|
android:gravity="center_vertical|end">
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/button_prev"
|
android:id="@+id/button_prev"
|
||||||
style="?actionButtonStyle"
|
style="?actionButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentStart="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:contentDescription="@string/prev_chapter"
|
android:contentDescription="@string/prev_chapter"
|
||||||
android:src="@drawable/ic_prev"
|
android:src="@drawable/ic_prev"
|
||||||
android:tooltipText="@string/prev_chapter" />
|
android:tooltipText="@string/prev_chapter" />
|
||||||
@@ -91,9 +90,7 @@
|
|||||||
android:id="@+id/slider"
|
android:id="@+id/slider"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_weight="1"
|
||||||
android:layout_toStartOf="@id/button_next"
|
|
||||||
android:layout_toEndOf="@id/button_prev"
|
|
||||||
android:stepSize="1.0"
|
android:stepSize="1.0"
|
||||||
android:valueFrom="0"
|
android:valueFrom="0"
|
||||||
app:labelBehavior="floating"
|
app:labelBehavior="floating"
|
||||||
@@ -105,13 +102,11 @@
|
|||||||
style="?actionButtonStyle"
|
style="?actionButtonStyle"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
|
||||||
android:layout_centerVertical="true"
|
|
||||||
android:contentDescription="@string/next_chapter"
|
android:contentDescription="@string/next_chapter"
|
||||||
android:src="@drawable/ic_next"
|
android:src="@drawable/ic_next"
|
||||||
android:tooltipText="@string/next_chapter" />
|
android:tooltipText="@string/next_chapter" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</com.google.android.material.appbar.MaterialToolbar>
|
</com.google.android.material.appbar.MaterialToolbar>
|
||||||
|
|
||||||
|
|||||||
@@ -124,4 +124,10 @@
|
|||||||
<item>@string/portrait</item>
|
<item>@string/portrait</item>
|
||||||
<item>@string/landscape</item>
|
<item>@string/landscape</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="reader_controls" translatable="false">
|
||||||
|
<item>@string/prev_chapter</item>
|
||||||
|
<item>@string/next_chapter</item>
|
||||||
|
<item>@string/pages_slider</item>
|
||||||
|
<item>@string/chapters_and_pages</item>
|
||||||
|
</string-array>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -795,4 +795,7 @@
|
|||||||
<string name="reader_info_bar_transparent">Transparent reader information bar</string>
|
<string name="reader_info_bar_transparent">Transparent reader information bar</string>
|
||||||
<string name="backup_restored_background">The backup will be restored in the background</string>
|
<string name="backup_restored_background">The backup will be restored in the background</string>
|
||||||
<string name="restoring_backup">Restoring backup</string>
|
<string name="restoring_backup">Restoring backup</string>
|
||||||
|
<string name="reader_controls_in_bottom_bar">Reader controls in bottom bar</string>
|
||||||
|
<string name="chapters_and_pages">Chapters and pages</string>
|
||||||
|
<string name="pages_slider">Page switch slider</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -138,7 +138,12 @@
|
|||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="pages_numbers"
|
android:key="pages_numbers"
|
||||||
android:summary="@string/show_pages_numbers_summary"
|
android:summary="@string/show_pages_numbers_summary"
|
||||||
android:title="@string/show_pages_numbers" />x
|
android:title="@string/show_pages_numbers" />
|
||||||
|
|
||||||
|
<MultiSelectListPreference
|
||||||
|
android:entries="@array/reader_controls"
|
||||||
|
android:key="reader_controls"
|
||||||
|
android:title="@string/reader_controls_in_bottom_bar" />
|
||||||
|
|
||||||
<ListPreference
|
<ListPreference
|
||||||
android:defaultValue="2"
|
android:defaultValue="2"
|
||||||
|
|||||||
Reference in New Issue
Block a user