mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-23 18:51:51 +01:00
Option to choose what buttons show up in the bottom reader sheet
+ Lots of optimizations/refactoring to custom preferences
This commit is contained in:
parent
053a5149c2
commit
f12be4a480
@ -73,6 +73,8 @@ object PreferenceKeys {
|
||||
|
||||
const val invertDoublePages = "invert_double_pages"
|
||||
|
||||
const val readerBottomButtons = "reader_bottom_buttons"
|
||||
|
||||
const val showNavigationOverlayNewUser = "reader_navigation_overlay_new_user"
|
||||
const val showNavigationOverlayNewUserWebtoon = "reader_navigation_overlay_new_user_webtoon"
|
||||
|
||||
|
@ -11,6 +11,7 @@ import com.f2prateek.rx.preferences.RxSharedPreferences
|
||||
import com.tfcporciuncula.flow.FlowSharedPreferences
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.track.TrackService
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PageLayout
|
||||
import eu.kanade.tachiyomi.ui.recents.RecentMangaAdapter
|
||||
@ -167,6 +168,11 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun invertDoublePages() = flowPrefs.getBoolean(Keys.invertDoublePages, false)
|
||||
|
||||
fun readerBottomButtons() = flowPrefs.getStringSet(
|
||||
Keys.readerBottomButtons,
|
||||
ReaderActivity.BUTTONS_DEFAULTS
|
||||
)
|
||||
|
||||
fun showNavigationOverlayNewUser() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUser, true)
|
||||
|
||||
fun showNavigationOverlayNewUserWebtoon() = flowPrefs.getBoolean(Keys.showNavigationOverlayNewUserWebtoon, true)
|
||||
|
@ -23,6 +23,7 @@ import android.view.WindowManager
|
||||
import android.view.animation.Animation
|
||||
import android.view.animation.AnimationUtils
|
||||
import android.widget.SeekBar
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.view.isVisible
|
||||
@ -194,6 +195,13 @@ class ReaderActivity :
|
||||
const val SHIFTED_PAGE_INDEX = "shiftedPageIndex"
|
||||
const val SHIFTED_CHAP_INDEX = "shiftedChapterIndex"
|
||||
|
||||
val BUTTONS_DEFAULTS = setOf(
|
||||
BottomButton.ViewChapters,
|
||||
BottomButton.WebView,
|
||||
BottomButton.PageLayout,
|
||||
BottomButton.CropBordersWebtoon
|
||||
).map { it.value }.toSet()
|
||||
|
||||
fun newIntent(context: Context, manga: Manga, chapter: Chapter): Intent {
|
||||
val intent = Intent(context, ReaderActivity::class.java)
|
||||
intent.putExtra("manga", manga.id)
|
||||
@ -203,6 +211,15 @@ class ReaderActivity :
|
||||
}
|
||||
}
|
||||
|
||||
enum class BottomButton(val value: String, @StringRes val stringRes: Int) {
|
||||
ViewChapters("vc", R.string.view_chapters),
|
||||
WebView("wb", R.string.open_in_webview),
|
||||
CropBordersPaged("cbp", R.string.crop_borders_paged),
|
||||
CropBordersWebtoon("cbw", R.string.crop_borders_webtoon),
|
||||
PageLayout("pl", R.string.page_layout),
|
||||
ShiftDoublePage("sdp", R.string.shift_double_pages)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the activity is created. Initializes the presenter and configuration.
|
||||
*/
|
||||
@ -324,8 +341,8 @@ class ReaderActivity :
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
|
||||
val splitItem = menu?.findItem(R.id.action_shift_double_page)
|
||||
splitItem?.isVisible = ((viewer as? PagerViewer)?.config?.doublePages ?: false) && !isTablet()
|
||||
binding.chaptersSheet.shiftPageButton.isVisible = ((viewer as? PagerViewer)?.config?.doublePages ?: false) && isTablet()
|
||||
splitItem?.isVisible = ((viewer as? PagerViewer)?.config?.doublePages ?: false) && !canShowSplitAtBottom()
|
||||
binding.chaptersSheet.shiftPageButton.isVisible = ((viewer as? PagerViewer)?.config?.doublePages ?: false) && canShowSplitAtBottom()
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
val icon = ContextCompat.getDrawable(
|
||||
this,
|
||||
@ -344,6 +361,14 @@ class ReaderActivity :
|
||||
return super.onPrepareOptionsMenu(menu)
|
||||
}
|
||||
|
||||
private fun canShowSplitAtBottom(): Boolean {
|
||||
return if (preferences.readerBottomButtons().isNotSet()) {
|
||||
isTablet()
|
||||
} else {
|
||||
BottomButton.ShiftDoublePage.value in preferences.readerBottomButtons().get()
|
||||
}
|
||||
}
|
||||
|
||||
fun setBottomNavButtons(pageLayout: Int) {
|
||||
val isDoublePage = pageLayout == PageLayout.DOUBLE_PAGES ||
|
||||
(pageLayout == PageLayout.AUTOMATIC && (viewer as? PagerViewer)?.config?.doublePages ?: false)
|
||||
@ -395,6 +420,19 @@ class ReaderActivity :
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateBasicShortcuts() {
|
||||
with(binding.chaptersSheet) {
|
||||
doublePage.isVisible = viewer is PagerViewer &&
|
||||
BottomButton.PageLayout.value in preferences.readerBottomButtons().get()
|
||||
cropBordersSheetButton.isVisible =
|
||||
if (viewer is PagerViewer) BottomButton.CropBordersPaged.value in preferences.readerBottomButtons().get()
|
||||
else BottomButton.CropBordersWebtoon.value in preferences.readerBottomButtons().get()
|
||||
webviewButton.isVisible = BottomButton.WebView.value in preferences.readerBottomButtons().get()
|
||||
chaptersButton.isVisible = BottomButton.ViewChapters.value in preferences.readerBottomButtons().get()
|
||||
shiftPageButton.isVisible = ((viewer as? PagerViewer)?.config?.doublePages ?: false) && canShowSplitAtBottom()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an item of the options menu was clicked. Used to handle clicks on our menu
|
||||
* entries.
|
||||
@ -527,19 +565,22 @@ class ReaderActivity :
|
||||
}
|
||||
}
|
||||
|
||||
binding.chaptersSheet.doublePage.setOnClickListener {
|
||||
if (preferences.pageLayout().get() == PageLayout.AUTOMATIC) {
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
config.doublePages = !config.doublePages
|
||||
reloadChapters(config.doublePages, true)
|
||||
with(binding.chaptersSheet) {
|
||||
doublePage.setOnClickListener {
|
||||
if (preferences.pageLayout().get() == PageLayout.AUTOMATIC) {
|
||||
(viewer as? PagerViewer)?.config?.let { config ->
|
||||
config.doublePages = !config.doublePages
|
||||
reloadChapters(config.doublePages, true)
|
||||
}
|
||||
} else {
|
||||
preferences.pageLayout().set(1 - preferences.pageLayout().get())
|
||||
}
|
||||
} else {
|
||||
preferences.pageLayout().set(1 - preferences.pageLayout().get())
|
||||
}
|
||||
}
|
||||
binding.chaptersSheet.cropBordersSheetButton.setOnClickListener {
|
||||
(viewer as? WebtoonViewer)?.let {
|
||||
val pref = if (it.hasMargins) preferences.cropBorders() else preferences.cropBordersWebtoon()
|
||||
cropBordersSheetButton.setOnClickListener {
|
||||
val pref =
|
||||
if ((viewer as? WebtoonViewer)?.hasMargins == true ||
|
||||
(viewer is PagerViewer)
|
||||
) preferences.cropBorders() else preferences.cropBordersWebtoon()
|
||||
pref.toggle()
|
||||
}
|
||||
}
|
||||
@ -793,8 +834,6 @@ class ReaderActivity :
|
||||
binding.viewerContainer.removeAllViews()
|
||||
}
|
||||
viewer = newViewer
|
||||
binding.chaptersSheet.doublePage.isVisible = viewer is PagerViewer
|
||||
binding.chaptersSheet.cropBordersSheetButton.isVisible = viewer !is PagerViewer
|
||||
binding.viewerContainer.addView(newViewer.getView())
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
@ -831,6 +870,7 @@ class ReaderActivity :
|
||||
binding.pleaseWait.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in_long))
|
||||
invalidateOptionsMenu()
|
||||
updateCropBordersShortcut()
|
||||
updateBasicShortcuts()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
@ -1351,6 +1391,12 @@ class ReaderActivity :
|
||||
setBottomNavButtons(it)
|
||||
}
|
||||
.launchIn(scope)
|
||||
|
||||
preferences.readerBottomButtons().asFlow()
|
||||
.onEach {
|
||||
updateBasicShortcuts()
|
||||
}
|
||||
.launchIn(scope)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,18 +95,6 @@ class SettingsDownloadController : SettingsController() {
|
||||
allSelectionRes = R.string.all
|
||||
|
||||
preferences.downloadNew().asImmediateFlow(viewScope) { isVisible = it }
|
||||
|
||||
preferences.downloadNewCategories().asImmediateFlow(viewScope) { list ->
|
||||
val selectedCategories = list
|
||||
.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
|
||||
.sortedBy { it.order }
|
||||
|
||||
summary = if (selectedCategories.isEmpty()) {
|
||||
resources?.getString(R.string.all)
|
||||
} else {
|
||||
selectedCategories.joinToString { it.name }
|
||||
}
|
||||
}
|
||||
}
|
||||
preferenceCategory {
|
||||
intListPreference(activity) {
|
||||
|
@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryController
|
||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -134,16 +133,6 @@ class SettingsLibraryController : SettingsController() {
|
||||
entries = dbCategories.map { it.name }
|
||||
entryValues = dbCategories.map { it.id.toString() }
|
||||
allSelectionRes = R.string.all
|
||||
|
||||
preferences.libraryUpdateCategories().asImmediateFlow { list ->
|
||||
val selectedCategories =
|
||||
list.mapNotNull { id -> dbCategories.find { it.id == id.toInt() } }
|
||||
.sortedBy { it.order }
|
||||
|
||||
summary =
|
||||
if (selectedCategories.isEmpty()) context.getString(R.string.all)
|
||||
else selectedCategories.joinToString { it.name }
|
||||
}
|
||||
}
|
||||
intListPreference(activity) {
|
||||
key = Keys.updateOnRefresh
|
||||
|
@ -4,6 +4,7 @@ import android.os.Build
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.ViewerNavigation
|
||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PageLayout
|
||||
import eu.kanade.tachiyomi.util.lang.addBetaTag
|
||||
@ -66,6 +67,18 @@ class SettingsReaderController : SettingsController() {
|
||||
defaultValue = 6
|
||||
summaryRes = R.string.amount_of_pages_to_preload
|
||||
}
|
||||
multiSelectListPreferenceMat(activity) {
|
||||
key = Keys.readerBottomButtons
|
||||
titleRes = R.string.display_buttons_bottom_reader
|
||||
val enumConstants = ReaderActivity.BottomButton::class.java.enumConstants
|
||||
entriesRes = enumConstants?.map { it.stringRes }.orEmpty().toTypedArray()
|
||||
entryValues = enumConstants?.map { it.value }.orEmpty()
|
||||
allSelectionRes = R.string.display_options
|
||||
allIsAlwaysSelected = true
|
||||
showAllLast = true
|
||||
defaultValue = ReaderActivity.BUTTONS_DEFAULTS
|
||||
}
|
||||
infoPreference(R.string.certain_buttons_can_be_found)
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
|
@ -23,7 +23,7 @@ open class ListMatPreference @JvmOverloads constructor(
|
||||
var entriesRes: Array<Int>
|
||||
get() = emptyArray()
|
||||
set(value) { entries = value.map { context.getString(it) } }
|
||||
protected var defValue: String = ""
|
||||
private var defValue: String = ""
|
||||
var entries: List<String> = emptyList()
|
||||
|
||||
override fun onSetInitialValue(defaultValue: Any?) {
|
||||
|
@ -50,6 +50,7 @@ open class MatPreference @JvmOverloads constructor(
|
||||
summaryProvider = customSummaryProvider
|
||||
return
|
||||
} else {
|
||||
customSummaryProvider = null
|
||||
summaryProvider = null
|
||||
}
|
||||
super.setSummary(summaryResId)
|
||||
@ -60,6 +61,7 @@ open class MatPreference @JvmOverloads constructor(
|
||||
summaryProvider = customSummaryProvider
|
||||
return
|
||||
} else {
|
||||
customSummaryProvider = null
|
||||
summaryProvider = null
|
||||
}
|
||||
super.setSummary(summary)
|
||||
|
@ -10,6 +10,7 @@ import com.afollestad.materialdialogs.list.isItemChecked
|
||||
import com.afollestad.materialdialogs.list.listItemsMultiChoice
|
||||
import com.afollestad.materialdialogs.list.uncheckItem
|
||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.ui.setting.defaultValue
|
||||
|
||||
class MultiListMatPreference @JvmOverloads constructor(
|
||||
activity: Activity?,
|
||||
@ -21,49 +22,80 @@ class MultiListMatPreference @JvmOverloads constructor(
|
||||
|
||||
var allSelectionRes: Int? = null
|
||||
|
||||
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
|
||||
prefs.getStringSet(key, emptySet<String>()).getOrDefault().mapNotNull {
|
||||
if (entryValues.indexOf(it) == -1) null
|
||||
else entryValues.indexOf(it) + if (allSelectionRes != null) 1 else 0
|
||||
}.toIntArray().joinToString(",") {
|
||||
entries[it]
|
||||
/** All item is always selected and uncheckabele */
|
||||
var allIsAlwaysSelected = false
|
||||
set(value) {
|
||||
field = value
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
/** All Item is moved to bottom of list if true */
|
||||
var showAllLast = false
|
||||
set(value) {
|
||||
field = value
|
||||
notifyChanged()
|
||||
}
|
||||
|
||||
private var defValue: Set<String> = emptySet()
|
||||
|
||||
override fun onSetInitialValue(defaultValue: Any?) {
|
||||
super.onSetInitialValue(defaultValue)
|
||||
defValue = (defaultValue as? Set<*>).orEmpty().mapNotNull { it as? String }.toSet()
|
||||
}
|
||||
|
||||
override var customSummaryProvider: SummaryProvider<MatPreference>? = SummaryProvider<MatPreference> {
|
||||
var values = prefs.getStringSet(key, defValue).getOrDefault().mapNotNull { value ->
|
||||
entryValues.indexOf(value).takeUnless { it == -1 }
|
||||
}.toIntArray().sorted().map { entries[it] }
|
||||
allSelectionRes?.let { allRes ->
|
||||
when {
|
||||
values.isEmpty() -> values = listOf(context.getString(allRes))
|
||||
allIsAlwaysSelected && !showAllLast ->
|
||||
values =
|
||||
listOf(context.getString(allRes)) + values
|
||||
allIsAlwaysSelected -> values = values + context.getString(allRes)
|
||||
}
|
||||
}
|
||||
values.joinToString()
|
||||
}
|
||||
|
||||
@SuppressLint("CheckResult")
|
||||
override fun MaterialDialog.setItems() {
|
||||
val set = prefs.getStringSet(key, emptySet()).getOrDefault()
|
||||
val set = prefs.getStringSet(key, defValue).getOrDefault()
|
||||
var default = set.mapNotNull {
|
||||
if (entryValues.indexOf(it) == -1) null
|
||||
else entryValues.indexOf(it) + if (allSelectionRes != null) 1 else 0
|
||||
else entryValues.indexOf(it) + if (allSelectionRes != null && !showAllLast) 1 else 0
|
||||
}
|
||||
.toIntArray()
|
||||
if (allSelectionRes != null && default.isEmpty()) default = intArrayOf(0)
|
||||
val items = if (allSelectionRes != null) {
|
||||
(listOf(context.getString(allSelectionRes!!)) + entries)
|
||||
if (showAllLast) entries + listOf(context.getString(allSelectionRes!!))
|
||||
else listOf(context.getString(allSelectionRes!!)) + entries
|
||||
} else entries
|
||||
val allPos = if (showAllLast) items.size - 1 else 0
|
||||
if (allSelectionRes != null && default.isEmpty()) default = intArrayOf(allPos)
|
||||
else if (allSelectionRes != null && allIsAlwaysSelected) default += allPos
|
||||
positiveButton(android.R.string.ok) {
|
||||
val pos = mutableListOf<Int>()
|
||||
for (i in items.indices)
|
||||
if (!(allSelectionRes != null && i == 0) && isItemChecked(i)) pos.add(i)
|
||||
if (!(allSelectionRes != null && i == allPos) && isItemChecked(i)) pos.add(i)
|
||||
var value = pos.mapNotNull {
|
||||
entryValues.getOrNull(it - if (allSelectionRes != null) 1 else 0)
|
||||
entryValues.getOrNull(it - if (allSelectionRes != null && !showAllLast) 1 else 0)
|
||||
}.toSet()
|
||||
if (allSelectionRes != null && isItemChecked(0)) value = emptySet()
|
||||
if (allSelectionRes != null && !allIsAlwaysSelected && isItemChecked(0)) value = emptySet()
|
||||
prefs.getStringSet(key, emptySet()).set(value)
|
||||
callChangeListener(value)
|
||||
this@MultiListMatPreference.summary = this@MultiListMatPreference.summary
|
||||
notifyChanged()
|
||||
}
|
||||
listItemsMultiChoice(
|
||||
items = items,
|
||||
allowEmptySelection = true,
|
||||
disabledIndices = if (allSelectionRes != null) intArrayOf(0) else null,
|
||||
disabledIndices = if (allSelectionRes != null) intArrayOf(allPos) else null,
|
||||
waitForPositiveButton = false,
|
||||
initialSelection = default
|
||||
) { _, pos, _ ->
|
||||
if (allSelectionRes != null) {
|
||||
if (pos.isEmpty()) checkItem(0)
|
||||
else uncheckItem(0)
|
||||
if (allSelectionRes != null && !allIsAlwaysSelected) {
|
||||
if (pos.isEmpty()) checkItem(allPos)
|
||||
else uncheckItem(allPos)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -166,6 +166,7 @@
|
||||
<string name="hide_hopper_on_scroll">Hide category hopper on scroll</string>
|
||||
<string name="more_library_settings">More library settings</string>
|
||||
<string name="shift_one_page_over">Shift one page over</string>
|
||||
<string name="shift_double_pages">Shift double pages</string>
|
||||
|
||||
<!-- Library update service notifications -->
|
||||
<string name="new_chapters_found">New chapters found</string>
|
||||
@ -198,6 +199,8 @@
|
||||
<string name="auto_refresh_covers_summary">Refresh covers in library as well
|
||||
when updating library</string>
|
||||
<string name="show_notification_error">Show a notification for errors</string>
|
||||
<string name="display_buttons_bottom_reader">Buttons at bottom of reader</string>
|
||||
<string name="certain_buttons_can_be_found">Certain buttons can be found in other places if disabled here</string>
|
||||
|
||||
<!-- Recents -->
|
||||
<string name="recents">Recents</string>
|
||||
@ -332,6 +335,8 @@
|
||||
performance</string>
|
||||
<string name="invert_double_pages">Invert double pages</string>
|
||||
<string name="crop_borders">Crop borders</string>
|
||||
<string name="crop_borders_paged">Crop borders (Paged)</string>
|
||||
<string name="crop_borders_webtoon">Crop borders (Webtoon)</string>
|
||||
<string name="remove_crop">Remove crop</string>
|
||||
<string name="use_custom_brightness">Use custom brightness</string>
|
||||
<string name="use_custom_color_filter">Use custom color filter</string>
|
||||
|
Loading…
Reference in New Issue
Block a user