Reader settings

This commit is contained in:
Koitharu
2020-03-03 18:57:37 +02:00
parent 22a6d06e1f
commit 6953ca21a9
18 changed files with 313 additions and 23 deletions

View File

@@ -27,7 +27,7 @@
android:name="android.app.default_searchable"
android:value=".ui.search.SearchActivity" />
</activity>
<activity android:name=".ui.details.MangaDetailsActivity" >
<activity android:name=".ui.details.MangaDetailsActivity">
<intent-filter>
<action android:name="${applicationId}.action.VIEW_MANGA" />
</intent-filter>
@@ -39,6 +39,9 @@
<activity
android:name=".ui.settings.SettingsActivity"
android:label="@string/settings" />
<activity
android:name=".ui.reader.SimpleSettingsActivity"
android:label="@string/settings" />
<service android:name=".ui.download.DownloadService" />

View File

@@ -6,10 +6,7 @@ import android.content.res.Resources
import androidx.appcompat.app.AppCompatDelegate
import androidx.preference.PreferenceManager
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.delegates.prefs.EnumPreferenceDelegate
import org.koitharu.kotatsu.utils.delegates.prefs.IntPreferenceDelegate
import org.koitharu.kotatsu.utils.delegates.prefs.NullableStringPreferenceDelegate
import org.koitharu.kotatsu.utils.delegates.prefs.StringIntPreferenceDelegate
import org.koitharu.kotatsu.utils.delegates.prefs.*
class AppSettings private constructor(resources: Resources, private val prefs: SharedPreferences) :
SharedPreferences by prefs {
@@ -35,6 +32,11 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
100
)
val readerPageSwitch by StringSetPreferenceDelegate(
resources.getString(R.string.key_reader_switchers),
setOf(PAGE_SWITCH_TAPS)
)
private var sourcesOrderStr by NullableStringPreferenceDelegate(resources.getString(R.string.key_sources_order))
var sourcesOrder: List<Int>
@@ -50,4 +52,10 @@ class AppSettings private constructor(resources: Resources, private val prefs: S
fun unsubscribe(listener: SharedPreferences.OnSharedPreferenceChangeListener) {
prefs.unregisterOnSharedPreferenceChangeListener(listener)
}
companion object {
const val PAGE_SWITCH_TAPS = "taps"
const val PAGE_SWITCH_VOLUME_KEYS = "volume"
}
}

View File

@@ -3,12 +3,10 @@ package org.koitharu.kotatsu.ui.reader
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.net.Uri
import android.os.Bundle
import android.view.Gravity
import android.view.Menu
import android.view.MenuItem
import android.view.MotionEvent
import android.view.*
import android.widget.Toast
import androidx.core.view.isVisible
import androidx.core.view.updatePadding
@@ -17,11 +15,13 @@ import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.activity_reader.*
import moxy.MvpDelegate
import moxy.ktx.moxyPresenter
import org.koin.core.inject
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.Manga
import org.koitharu.kotatsu.core.model.MangaChapter
import org.koitharu.kotatsu.core.model.MangaHistory
import org.koitharu.kotatsu.core.model.MangaPage
import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.ui.common.BaseFullscreenActivity
import org.koitharu.kotatsu.ui.reader.standard.StandardReaderFragment
@@ -35,14 +35,17 @@ import org.koitharu.kotatsu.utils.ext.*
class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnChapterChangeListener,
GridTouchHelper.OnGridTouchListener, OnPageSelectListener, ReaderConfigDialog.Callback,
ReaderListener {
ReaderListener, SharedPreferences.OnSharedPreferenceChangeListener {
private val presenter by moxyPresenter(factory = ReaderPresenter.Companion::getInstance)
private val settings by inject<AppSettings>()
lateinit var state: ReaderState
private set
private lateinit var touchHelper: GridTouchHelper
private var isTapSwitchEnabled = true
private var isVolumeKeysSwitchEnabled = false
private val reader
get() = supportFragmentManager.findFragmentById(R.id.container) as? BaseReaderFragment
@@ -74,6 +77,9 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
insets
}
settings.subscribe(this)
loadSettings()
if (savedInstanceState?.containsKey(MvpDelegate.MOXY_DELEGATE_TAGS_KEY) != true) {
presenter.loadChapter(state.manga, state.chapterId, ReaderAction.REPLACE)
}
@@ -95,6 +101,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
super.onPause()
}
override fun onDestroy() {
settings.unsubscribe(this)
super.onDestroy()
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.opt_reader_top, menu)
return super.onCreateOptionsMenu(menu)
@@ -106,7 +117,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
}
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
R.id.action_settings -> {
R.id.action_reader_mode -> {
ReaderConfigDialog.show(
supportFragmentManager, when (reader) {
is StandardReaderFragment -> ReaderMode.STANDARD
@@ -116,6 +127,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
)
true
}
R.id.action_settings -> {
startActivity(SimpleSettingsActivity.newReaderSettingsIntent(this))
true
}
R.id.action_chapters -> {
ChaptersDialog.show(
supportFragmentManager,
@@ -183,11 +198,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
setUiIsVisible(!appbar_top.isVisible)
}
GridTouchHelper.AREA_TOP,
GridTouchHelper.AREA_LEFT -> {
GridTouchHelper.AREA_LEFT -> if (isTapSwitchEnabled) {
reader?.switchPageBy(-1)
}
GridTouchHelper.AREA_BOTTOM,
GridTouchHelper.AREA_RIGHT -> {
GridTouchHelper.AREA_RIGHT -> if (isTapSwitchEnabled) {
reader?.switchPageBy(1)
}
}
@@ -209,6 +224,45 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
return super.dispatchTouchEvent(ev)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean = when (keyCode) {
KeyEvent.KEYCODE_VOLUME_UP -> if (isVolumeKeysSwitchEnabled) {
reader?.switchPageBy(-1)
true
} else {
super.onKeyDown(keyCode, event)
}
KeyEvent.KEYCODE_VOLUME_DOWN -> if (isVolumeKeysSwitchEnabled) {
reader?.switchPageBy(1)
true
} else {
super.onKeyDown(keyCode, event)
}
KeyEvent.KEYCODE_SPACE,
KeyEvent.KEYCODE_PAGE_DOWN,
KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_DPAD_RIGHT -> {
reader?.switchPageBy(1)
true
}
KeyEvent.KEYCODE_PAGE_UP,
KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_DPAD_LEFT -> {
reader?.switchPageBy(-1)
true
}
KeyEvent.KEYCODE_DPAD_CENTER -> {
setUiIsVisible(!appbar_top.isVisible)
true
}
else -> super.onKeyDown(keyCode, event)
}
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
return (isVolumeKeysSwitchEnabled &&
(keyCode == KeyEvent.KEYCODE_VOLUME_DOWN || keyCode == KeyEvent.KEYCODE_VOLUME_UP))
|| super.onKeyUp(keyCode, event)
}
override fun onChapterChanged(chapter: MangaChapter) {
state = state.copy(
chapterId = chapter.id,
@@ -262,6 +316,10 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
}
}
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
loadSettings()
}
private fun showWaitWhileLoading() {
Toast.makeText(this, R.string.wait_for_loading_finish, Toast.LENGTH_SHORT).apply {
setGravity(Gravity.CENTER, 0, 0)
@@ -296,6 +354,17 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
}
}
}
toolbar_bottom.menu.findItem(R.id.action_reader_mode).setIcon(when(mode) {
ReaderMode.WEBTOON -> R.drawable.ic_script
else -> R.drawable.ic_book_page
})
}
private fun loadSettings() {
settings.readerPageSwitch.let {
isTapSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_TAPS)
isVolumeKeysSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_VOLUME_KEYS)
}
}
companion object {

View File

@@ -0,0 +1,35 @@
package org.koitharu.kotatsu.ui.reader
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.commit
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.ui.common.BaseActivity
import org.koitharu.kotatsu.ui.settings.ReaderSettingsFragment
import org.koitharu.kotatsu.ui.settings.SettingsHeadersFragment
class SimpleSettingsActivity : BaseActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_settings_simple)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
val section = intent?.getIntExtra(EXTRA_SECTION, 0)
supportFragmentManager.commit {
replace(R.id.container, when(section) {
SECTION_READER -> ReaderSettingsFragment()
else -> SettingsHeadersFragment()
})
}
}
companion object {
private const val EXTRA_SECTION = "section"
private const val SECTION_READER = 1
fun newReaderSettingsIntent(context: Context) = Intent(context, SimpleSettingsActivity::class.java)
.putExtra(EXTRA_SECTION, SECTION_READER)
}
}

View File

@@ -0,0 +1,17 @@
package org.koitharu.kotatsu.ui.settings
import android.os.Bundle
import androidx.preference.MultiSelectListPreference
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.ui.common.BasePreferenceFragment
import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
class ReaderSettingsFragment : BasePreferenceFragment(R.string.reader_settings) {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
addPreferencesFromResource(R.xml.pref_reader)
findPreference<MultiSelectListPreference>(R.string.key_reader_switchers)?.let {
it.summaryProvider = MultiSummaryProvider()
}
}
}

View File

@@ -0,0 +1,20 @@
package org.koitharu.kotatsu.ui.settings.utils
import android.annotation.SuppressLint
import androidx.preference.MultiSelectListPreference
import androidx.preference.Preference
class MultiSummaryProvider : Preference.SummaryProvider<MultiSelectListPreference> {
@SuppressLint("PrivateResource")
override fun provideSummary(preference: MultiSelectListPreference): CharSequence {
val values = preference.values
return if (values.isEmpty()) {
return preference.context.getString(androidx.preference.R.string.not_set)
} else {
values.joinToString(", ") {
preference.entries[preference.findIndexOfValue(it)]
}
}
}
}

View File

@@ -0,0 +1,20 @@
package org.koitharu.kotatsu.utils.delegates.prefs
import android.content.SharedPreferences
import androidx.core.content.edit
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class BoolPreferenceDelegate(private val key: String, private val defValue: Boolean) :
ReadWriteProperty<SharedPreferences, Boolean> {
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Boolean {
return thisRef.getBoolean(key, defValue)
}
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Boolean) {
thisRef.edit {
putBoolean(key, value)
}
}
}

View File

@@ -0,0 +1,20 @@
package org.koitharu.kotatsu.utils.delegates.prefs
import android.content.SharedPreferences
import androidx.core.content.edit
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
class StringSetPreferenceDelegate(private val key: String, private val defValue: Set<String>) :
ReadWriteProperty<SharedPreferences, Set<String>> {
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): Set<String> {
return thisRef.getStringSet(key, defValue) ?: defValue
}
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: Set<String>) {
thisRef.edit {
putStringSet(key, value)
}
}
}

View File

@@ -0,0 +1,12 @@
<!-- drawable/book_outline.xml -->
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M18,2A2,2 0 0,1 20,4V20A2,2 0 0,1 18,22H6A2,2 0 0,1 4,20V4A2,2 0 0,1 6,2H18M18,4H13V12L10.5,9.75L8,12V4H6V20H18V4Z" />
</vector>

View File

@@ -0,0 +1,8 @@
<!-- drawable/information_outline.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#000" android:pathData="M11,9H13V7H11M12,20C7.59,20 4,16.41 4,12C4,7.59 7.59,4 12,4C16.41,4 20,7.59 20,12C20,16.41 16.41,20 12,20M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M11,17H13V11H11V17Z" />
</vector>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?colorPrimary"
android:fitsSystemWindows="true"
android:theme="@style/AppToolbarTheme">
<androidx.appcompat.widget.Toolbar
android:id="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="?android:actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppPopupTheme" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.fragment.app.FragmentContainerView
android:id="@id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@@ -1,31 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<menu
xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:ignore="AlwaysShowAction">
<item
android:id="@+id/action_bookmark_add"
android:icon="@drawable/ic_bookmark_add"
android:title="@string/add_bookmark"
android:visible="false"
app:showAsAction="ifRoom" />
app:showAsAction="always" />
<item
android:id="@+id/action_save_page"
android:icon="@drawable/ic_page_image"
android:title="@string/save_page"
app:showAsAction="ifRoom" />
app:showAsAction="always" />
<item
android:id="@+id/action_pages_thumbs"
android:icon="@drawable/ic_grid"
android:title="@string/pages"
app:showAsAction="ifRoom" />
app:showAsAction="always" />
<item
android:id="@+id/action_reader_mode"
android:icon="@drawable/ic_book_page"
android:title="@string/read_mode"
app:showAsAction="always" />
<item
android:id="@+id/action_settings"
android:icon="@drawable/ic_tune"
android:title="@string/settings"
app:showAsAction="ifRoom" />
app:showAsAction="always" />
</menu>

View File

@@ -86,4 +86,8 @@
<string name="search_results_on_s">Результаты поиска по %s</string>
<string name="delete_manga">Удалить мангу</string>
<string name="text_delete_local_manga">Вы уверены, что хотите удалить \"%s\" с устройства? \nЭто действие нельзя будет отменить.</string>
<string name="reader_settings">Настройки чтения</string>
<string name="switch_pages">Листание страниц</string>
<string name="taps_on_edges">Нажатия по краям</string>
<string name="volume_buttons">Кнопки громкости</string>
</resources>

View File

@@ -1,8 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="themes">
<item>@string/automatic</item>
<item>@string/light</item>
<item>@string/dark</item>
</string-array>
<string-array name="themes">
<item>@string/automatic</item>
<item>@string/light</item>
<item>@string/dark</item>
</string-array>
<string-array name="reader_switchers">
<item>@string/taps_on_edges</item>
<item>@string/volume_buttons</item>
</string-array>
</resources>

View File

@@ -5,9 +5,17 @@
<string name="key_sources_order">sources_order</string>
<string name="key_pages_cache_clear">pages_cache_clear</string>
<string name="key_grid_size">grid_size</string>
<string name="key_reader_switchers">reader_switchers</string>
<string-array name="values_theme">
<item>-1</item>
<item>1</item>
<item>2</item>
</string-array>
<string-array name="values_reader_switchers">
<item>taps</item>
<item>volume</item>
</string-array>
<string-array name="values_reader_switchers_default">
<item>taps</item>
</string-array>
</resources>

View File

@@ -87,4 +87,8 @@
<string name="search_results_on_s">Search results on %s</string>
<string name="delete_manga">Delete manga</string>
<string name="text_delete_local_manga">Are you really want to delete \"%s\" from your phone\'s local storage? \nThis operation cannot be undone.</string>
<string name="reader_settings">Reader settings</string>
<string name="switch_pages">Switch pages</string>
<string name="taps_on_edges">Taps on edges</string>
<string name="volume_buttons">Volume buttons</string>
</resources>

View File

@@ -12,6 +12,11 @@
android:icon="@drawable/ic_web"
android:title="@string/remote_sources" />
<PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.ReaderSettingsFragment"
android:icon="@drawable/ic_book"
android:title="@string/reader_settings" />
<PreferenceScreen
android:fragment="org.koitharu.kotatsu.ui.settings.HistorySettingsFragment"
android:icon="@drawable/ic_history"

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<MultiSelectListPreference
android:defaultValue="@array/values_reader_switchers_default"
android:entries="@array/reader_switchers"
android:entryValues="@array/values_reader_switchers"
android:key="@string/key_reader_switchers"
android:title="@string/switch_pages"
app:iconSpaceReserved="false" />
</PreferenceScreen>