Scale mode option for reader
This commit is contained in:
@@ -16,7 +16,7 @@ android {
|
|||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode gitCommits
|
versionCode gitCommits
|
||||||
versionName '0.5.4'
|
versionName '1.0-a1'
|
||||||
|
|
||||||
kapt {
|
kapt {
|
||||||
arguments {
|
arguments {
|
||||||
@@ -63,8 +63,8 @@ tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).all {
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.1'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.0'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.5.0-alpha04'
|
implementation 'androidx.core:core-ktx:1.5.0-alpha04'
|
||||||
implementation 'androidx.activity:activity-ktx:1.2.0-beta01'
|
implementation 'androidx.activity:activity-ktx:1.2.0-beta01'
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
package org.koitharu.kotatsu.core.model
|
||||||
|
|
||||||
|
enum class ZoomMode {
|
||||||
|
|
||||||
|
FIT_CENTER, FIT_HEIGHT, FIT_WIDTH, KEEP_START
|
||||||
|
}
|
||||||
@@ -6,11 +6,13 @@ import org.koitharu.kotatsu.core.model.MangaTag
|
|||||||
import org.koitharu.kotatsu.core.model.SortOrder
|
import org.koitharu.kotatsu.core.model.SortOrder
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
|
|
||||||
abstract class RemoteMangaRepository(protected val loaderContext: MangaLoaderContext) : MangaRepository {
|
abstract class RemoteMangaRepository(
|
||||||
|
protected val loaderContext: MangaLoaderContext
|
||||||
|
) : MangaRepository {
|
||||||
|
|
||||||
protected abstract val source: MangaSource
|
protected abstract val source: MangaSource
|
||||||
|
|
||||||
protected val conf by lazy(LazyThreadSafetyMode.NONE) {
|
protected val conf by lazy {
|
||||||
loaderContext.getSettings(source)
|
loaderContext.getSettings(source)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(
|
abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(
|
||||||
loaderContext
|
loaderContext
|
||||||
@@ -14,7 +15,7 @@ abstract class ChanRepository(loaderContext: MangaLoaderContext) : RemoteMangaRe
|
|||||||
|
|
||||||
protected abstract val defaultDomain: String
|
protected abstract val defaultDomain: String
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
SortOrder.NEWEST,
|
SortOrder.NEWEST,
|
||||||
SortOrder.POPULARITY,
|
SortOrder.POPULARITY,
|
||||||
SortOrder.ALPHABETICAL
|
SortOrder.ALPHABETICAL
|
||||||
|
|||||||
@@ -7,12 +7,14 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) {
|
class DesuMeRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) {
|
||||||
|
|
||||||
override val source = MangaSource.DESUME
|
override val source = MangaSource.DESUME
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
SortOrder.UPDATED,
|
SortOrder.UPDATED,
|
||||||
SortOrder.POPULARITY,
|
SortOrder.POPULARITY,
|
||||||
SortOrder.NEWEST,
|
SortOrder.NEWEST,
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
abstract class GroupleRepository(loaderContext: MangaLoaderContext) :
|
||||||
RemoteMangaRepository(loaderContext) {
|
RemoteMangaRepository(loaderContext) {
|
||||||
|
|
||||||
protected abstract val defaultDomain: String
|
protected abstract val defaultDomain: String
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
SortOrder.UPDATED, SortOrder.POPULARITY,
|
SortOrder.UPDATED, SortOrder.POPULARITY,
|
||||||
SortOrder.NEWEST, SortOrder.RATING
|
SortOrder.NEWEST, SortOrder.RATING
|
||||||
//FIXME SortOrder.ALPHABETICAL
|
//FIXME SortOrder.ALPHABETICAL
|
||||||
|
|||||||
@@ -4,13 +4,14 @@ import androidx.collection.ArraySet
|
|||||||
import androidx.collection.arraySetOf
|
import androidx.collection.arraySetOf
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.core.exceptions.ParseException
|
import org.koitharu.kotatsu.core.exceptions.ParseException
|
||||||
import org.koitharu.kotatsu.core.model.*
|
import org.koitharu.kotatsu.core.model.*
|
||||||
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
||||||
RemoteMangaRepository(loaderContext) {
|
RemoteMangaRepository(loaderContext) {
|
||||||
@@ -19,7 +20,7 @@ open class MangaLibRepository(loaderContext: MangaLoaderContext) :
|
|||||||
|
|
||||||
override val source = MangaSource.MANGALIB
|
override val source = MangaSource.MANGALIB
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
SortOrder.RATING,
|
SortOrder.RATING,
|
||||||
SortOrder.ALPHABETICAL,
|
SortOrder.ALPHABETICAL,
|
||||||
SortOrder.POPULARITY,
|
SortOrder.POPULARITY,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ class MangaTownRepository(loaderContext: MangaLoaderContext) :
|
|||||||
|
|
||||||
override val source = MangaSource.MANGATOWN
|
override val source = MangaSource.MANGATOWN
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
SortOrder.ALPHABETICAL,
|
SortOrder.ALPHABETICAL,
|
||||||
SortOrder.RATING,
|
SortOrder.RATING,
|
||||||
SortOrder.POPULARITY,
|
SortOrder.POPULARITY,
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class MangareadRepository(
|
class MangareadRepository(
|
||||||
loaderContext: MangaLoaderContext
|
loaderContext: MangaLoaderContext
|
||||||
@@ -14,7 +15,10 @@ class MangareadRepository(
|
|||||||
|
|
||||||
override val source = MangaSource.MANGAREAD
|
override val source = MangaSource.MANGAREAD
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(SortOrder.UPDATED, SortOrder.POPULARITY)
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
|
SortOrder.UPDATED,
|
||||||
|
SortOrder.POPULARITY
|
||||||
|
)
|
||||||
|
|
||||||
override suspend fun getList(
|
override suspend fun getList(
|
||||||
offset: Int,
|
offset: Int,
|
||||||
|
|||||||
@@ -7,13 +7,18 @@ import org.koitharu.kotatsu.core.parser.RemoteMangaRepository
|
|||||||
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
import org.koitharu.kotatsu.core.prefs.SourceSettings
|
||||||
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
import org.koitharu.kotatsu.domain.MangaLoaderContext
|
||||||
import org.koitharu.kotatsu.utils.ext.*
|
import org.koitharu.kotatsu.utils.ext.*
|
||||||
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) {
|
class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaRepository(loaderContext) {
|
||||||
|
|
||||||
override val source = MangaSource.NUDEMOON
|
override val source = MangaSource.NUDEMOON
|
||||||
|
|
||||||
override val sortOrders = arraySetOf(SortOrder.NEWEST, SortOrder.POPULARITY, SortOrder.RATING)
|
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||||
|
SortOrder.NEWEST,
|
||||||
|
SortOrder.POPULARITY,
|
||||||
|
SortOrder.RATING
|
||||||
|
)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
loaderContext.insertCookies(
|
loaderContext.insertCookies(
|
||||||
@@ -35,9 +40,7 @@ class NudeMoonRepository(loaderContext: MangaLoaderContext) : RemoteMangaReposit
|
|||||||
tag != null -> "https://$domain/tags/${tag.key}&rowstart=$offset"
|
tag != null -> "https://$domain/tags/${tag.key}&rowstart=$offset"
|
||||||
else -> "https://$domain/all_manga?${getSortKey(sortOrder)}&rowstart=$offset"
|
else -> "https://$domain/all_manga?${getSortKey(sortOrder)}&rowstart=$offset"
|
||||||
}
|
}
|
||||||
val doc = loaderContext.httpGet(url) {
|
val doc = loaderContext.httpGet(url).parseHtml()
|
||||||
addHeader("Cookie", "NMfYa=1; nm_mobile=0;")
|
|
||||||
}.parseHtml()
|
|
||||||
val root = doc.body().run {
|
val root = doc.body().run {
|
||||||
selectFirst("td.shoutbox") ?: selectFirst("td.main-bg")
|
selectFirst("td.shoutbox") ?: selectFirst("td.main-bg")
|
||||||
} ?: throw ParseException("Cannot find root")
|
} ?: throw ParseException("Cannot find root")
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import androidx.appcompat.app.AppCompatDelegate
|
|||||||
import androidx.collection.arraySetOf
|
import androidx.collection.arraySetOf
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
import org.koitharu.kotatsu.core.parser.LocalMangaRepository
|
||||||
import org.koitharu.kotatsu.utils.delegates.prefs.*
|
import org.koitharu.kotatsu.utils.delegates.prefs.*
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -18,13 +19,13 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
|||||||
PreferenceManager.getDefaultSharedPreferences(context)
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
)
|
)
|
||||||
|
|
||||||
var listMode by EnumPreferenceDelegate(
|
var listMode by IntEnumPreferenceDelegate(
|
||||||
ListMode::class.java,
|
ListMode::class.java,
|
||||||
KEY_LIST_MODE,
|
KEY_LIST_MODE,
|
||||||
ListMode.DETAILED_LIST
|
ListMode.DETAILED_LIST
|
||||||
)
|
)
|
||||||
|
|
||||||
var defaultSection by EnumPreferenceDelegate(
|
var defaultSection by IntEnumPreferenceDelegate(
|
||||||
AppSection::class.java,
|
AppSection::class.java,
|
||||||
KEY_APP_SECTION,
|
KEY_APP_SECTION,
|
||||||
AppSection.HISTORY
|
AppSection.HISTORY
|
||||||
@@ -66,6 +67,12 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
|||||||
|
|
||||||
val isPreferRtlReader by BoolPreferenceDelegate(KEY_READER_PREFER_RTL, false)
|
val isPreferRtlReader by BoolPreferenceDelegate(KEY_READER_PREFER_RTL, false)
|
||||||
|
|
||||||
|
val zoomMode by EnumPreferenceDelegate(
|
||||||
|
ZoomMode::class.java,
|
||||||
|
KEY_ZOOM_MODE,
|
||||||
|
ZoomMode.FIT_CENTER
|
||||||
|
)
|
||||||
|
|
||||||
val trackSources by StringSetPreferenceDelegate(
|
val trackSources by StringSetPreferenceDelegate(
|
||||||
KEY_TRACK_SOURCES,
|
KEY_TRACK_SOURCES,
|
||||||
arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
arraySetOf(TRACK_FAVOURITES, TRACK_HISTORY)
|
||||||
@@ -143,5 +150,6 @@ class AppSettings private constructor(private val prefs: SharedPreferences) :
|
|||||||
const val KEY_APP_PASSWORD = "app_password"
|
const val KEY_APP_PASSWORD = "app_password"
|
||||||
const val KEY_PROTECT_APP = "protect_app"
|
const val KEY_PROTECT_APP = "protect_app"
|
||||||
const val KEY_APP_VERSION = "app_version"
|
const val KEY_APP_VERSION = "app_version"
|
||||||
|
const val KEY_ZOOM_MODE = "zoom_mode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,20 +13,16 @@ open class MangaLoaderContext : KoinComponent {
|
|||||||
private val okHttp by inject<OkHttpClient>()
|
private val okHttp by inject<OkHttpClient>()
|
||||||
private val cookieJar by inject<CookieJar>()
|
private val cookieJar by inject<CookieJar>()
|
||||||
|
|
||||||
suspend fun httpGet(url: String, block: (Request.Builder.() -> Unit)? = null): Response {
|
suspend fun httpGet(url: String): Response {
|
||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.get()
|
.get()
|
||||||
.url(url)
|
.url(url)
|
||||||
if (block != null) {
|
|
||||||
request.block()
|
|
||||||
}
|
|
||||||
return okHttp.newCall(request.build()).await()
|
return okHttp.newCall(request.build()).await()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun httpPost(
|
suspend fun httpPost(
|
||||||
url: String,
|
url: String,
|
||||||
form: Map<String, String>,
|
form: Map<String, String>
|
||||||
block: (Request.Builder.() -> Unit)? = null
|
|
||||||
): Response {
|
): Response {
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
form.forEach { (k, v) ->
|
form.forEach { (k, v) ->
|
||||||
@@ -35,16 +31,12 @@ open class MangaLoaderContext : KoinComponent {
|
|||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.post(body.build())
|
.post(body.build())
|
||||||
.url(url)
|
.url(url)
|
||||||
if (block != null) {
|
|
||||||
request.block()
|
|
||||||
}
|
|
||||||
return okHttp.newCall(request.build()).await()
|
return okHttp.newCall(request.build()).await()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun httpPost(
|
suspend fun httpPost(
|
||||||
url: String,
|
url: String,
|
||||||
payload: String,
|
payload: String
|
||||||
block: (Request.Builder.() -> Unit)? = null
|
|
||||||
): Response {
|
): Response {
|
||||||
val body = FormBody.Builder()
|
val body = FormBody.Builder()
|
||||||
payload.split('&').forEach {
|
payload.split('&').forEach {
|
||||||
@@ -58,9 +50,6 @@ open class MangaLoaderContext : KoinComponent {
|
|||||||
val request = Request.Builder()
|
val request = Request.Builder()
|
||||||
.post(body.build())
|
.post(body.build())
|
||||||
.url(url)
|
.url(url)
|
||||||
if (block != null) {
|
|
||||||
request.block()
|
|
||||||
}
|
|
||||||
return okHttp.newCall(request.build()).await()
|
return okHttp.newCall(request.build()).await()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.ui.reader
|
|
||||||
|
|
||||||
enum class ReaderAction {
|
|
||||||
REPLACE, PREPEND, APPEND
|
|
||||||
}
|
|
||||||
@@ -96,7 +96,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
ViewCompat.setOnApplyWindowInsetsListener(rootLayout, this)
|
ViewCompat.setOnApplyWindowInsetsListener(rootLayout, this)
|
||||||
|
|
||||||
settings.subscribe(this)
|
settings.subscribe(this)
|
||||||
loadSettings()
|
loadSwitchSettings()
|
||||||
orientationHelper.observeAutoOrientation()
|
orientationHelper.observeAutoOrientation()
|
||||||
.onEach {
|
.onEach {
|
||||||
toolbar_bottom.menu.findItem(R.id.action_screen_rotate).isVisible = !it
|
toolbar_bottom.menu.findItem(R.id.action_screen_rotate).isVisible = !it
|
||||||
@@ -370,7 +370,11 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
|
||||||
loadSettings()
|
when (key) {
|
||||||
|
AppSettings.KEY_READER_SWITCHERS -> loadSwitchSettings()
|
||||||
|
AppSettings.KEY_READER_ANIMATION,
|
||||||
|
AppSettings.KEY_ZOOM_MODE -> reader?.recreateAdapter()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showWaitWhileLoading() {
|
private fun showWaitWhileLoading() {
|
||||||
@@ -410,7 +414,7 @@ class ReaderActivity : BaseFullscreenActivity(), ReaderView, ChaptersDialog.OnCh
|
|||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSettings() {
|
private fun loadSwitchSettings() {
|
||||||
settings.readerPageSwitch.let {
|
settings.readerPageSwitch.let {
|
||||||
isTapSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_TAPS)
|
isTapSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_TAPS)
|
||||||
isVolumeKeysSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_VOLUME_KEYS)
|
isVolumeKeysSwitchEnabled = it.contains(AppSettings.PAGE_SWITCH_VOLUME_KEYS)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.ui.reader.base
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.annotation.CallSuper
|
||||||
import androidx.collection.LongSparseArray
|
import androidx.collection.LongSparseArray
|
||||||
import androidx.core.view.postDelayed
|
import androidx.core.view.postDelayed
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
@@ -131,6 +132,11 @@ abstract class AbstractReader(contentLayoutId: Int) : BaseFragment(contentLayout
|
|||||||
super.onDestroy()
|
super.onDestroy()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@CallSuper
|
||||||
|
open fun recreateAdapter() {
|
||||||
|
adapter = onCreateAdapter(pages)
|
||||||
|
}
|
||||||
|
|
||||||
fun getPages(): List<MangaPage>? {
|
fun getPages(): List<MangaPage>? {
|
||||||
val chapterId = (pages.getOrNull(getCurrentItem()) ?: return null).chapterId
|
val chapterId = (pages.getOrNull(getCurrentItem()) ?: return null).chapterId
|
||||||
// TODO optimize
|
// TODO optimize
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import android.net.Uri
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
|
import org.koin.core.component.inject
|
||||||
import org.koitharu.kotatsu.core.model.MangaPage
|
import org.koitharu.kotatsu.core.model.MangaPage
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.ui.reader.PageLoader
|
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||||
import org.koitharu.kotatsu.utils.ext.launchAfter
|
import org.koitharu.kotatsu.utils.ext.launchAfter
|
||||||
import org.koitharu.kotatsu.utils.ext.launchInstead
|
import org.koitharu.kotatsu.utils.ext.launchInstead
|
||||||
@@ -14,8 +17,10 @@ import java.io.IOException
|
|||||||
class PageHolderDelegate(
|
class PageHolderDelegate(
|
||||||
private val loader: PageLoader,
|
private val loader: PageLoader,
|
||||||
private val callback: Callback
|
private val callback: Callback
|
||||||
) : SubsamplingScaleImageView.DefaultOnImageEventListener(), CoroutineScope by loader {
|
) : SubsamplingScaleImageView.DefaultOnImageEventListener(),
|
||||||
|
CoroutineScope by loader {
|
||||||
|
|
||||||
|
private val settings by loader.inject<AppSettings>()
|
||||||
private var state = State.EMPTY
|
private var state = State.EMPTY
|
||||||
private var job: Job? = null
|
private var job: Job? = null
|
||||||
private var file: File? = null
|
private var file: File? = null
|
||||||
@@ -36,7 +41,7 @@ class PageHolderDelegate(
|
|||||||
|
|
||||||
override fun onReady() {
|
override fun onReady() {
|
||||||
state = State.SHOWING
|
state = State.SHOWING
|
||||||
callback.onImageShowing()
|
callback.onImageShowing(settings.zoomMode)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onImageLoaded() {
|
override fun onImageLoaded() {
|
||||||
@@ -99,7 +104,7 @@ class PageHolderDelegate(
|
|||||||
|
|
||||||
fun onImageReady(uri: Uri)
|
fun onImageReady(uri: Uri)
|
||||||
|
|
||||||
fun onImageShowing()
|
fun onImageShowing(zoom: ZoomMode)
|
||||||
|
|
||||||
fun onImageShown()
|
fun onImageShown()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package org.koitharu.kotatsu.ui.reader.reversed
|
||||||
|
|
||||||
|
import android.graphics.PointF
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
|
import kotlinx.android.synthetic.main.item_page.*
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
|
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||||
|
import org.koitharu.kotatsu.ui.reader.standard.PageHolder
|
||||||
|
|
||||||
|
class ReversedPageHolder(parent: ViewGroup, loader: PageLoader) : PageHolder(parent, loader) {
|
||||||
|
|
||||||
|
override fun onImageShowing(zoom: ZoomMode) {
|
||||||
|
ssiv.maxScale = 2f * maxOf(
|
||||||
|
ssiv.width / ssiv.sWidth.toFloat(),
|
||||||
|
ssiv.height / ssiv.sHeight.toFloat()
|
||||||
|
)
|
||||||
|
when (zoom) {
|
||||||
|
ZoomMode.FIT_CENTER -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE)
|
||||||
|
ssiv.resetScaleAndCenter()
|
||||||
|
}
|
||||||
|
ZoomMode.FIT_HEIGHT -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
||||||
|
ssiv.minScale = ssiv.height / ssiv.sHeight.toFloat()
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.minScale,
|
||||||
|
PointF(ssiv.sWidth.toFloat(), ssiv.sHeight / 2f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ZoomMode.FIT_WIDTH -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
||||||
|
ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat()
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.minScale,
|
||||||
|
PointF(ssiv.sWidth / 2f, 0f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ZoomMode.KEEP_START -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE)
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.maxScale,
|
||||||
|
PointF(ssiv.sWidth.toFloat(), 0f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,14 +5,13 @@ import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
|||||||
import org.koitharu.kotatsu.ui.reader.PageLoader
|
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||||
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
||||||
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
||||||
import org.koitharu.kotatsu.ui.reader.standard.PageHolder
|
|
||||||
|
|
||||||
class ReversedPagesAdapter(
|
class ReversedPagesAdapter(
|
||||||
pages: List<ReaderPage>,
|
pages: List<ReaderPage>,
|
||||||
private val loader: PageLoader
|
private val loader: PageLoader
|
||||||
) : BaseReaderAdapter(pages) {
|
) : BaseReaderAdapter(pages) {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup) = PageHolder(parent, loader)
|
override fun onCreateViewHolder(parent: ViewGroup) = ReversedPageHolder(parent, loader)
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: BaseViewHolder<ReaderPage, Unit>, position: Int) {
|
override fun onBindViewHolder(holder: BaseViewHolder<ReaderPage, Unit>, position: Int) {
|
||||||
super.onBindViewHolder(holder, reversed(position))
|
super.onBindViewHolder(holder, reversed(position))
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
|||||||
import org.koitharu.kotatsu.ui.reader.standard.PageAnimTransformer
|
import org.koitharu.kotatsu.ui.reader.standard.PageAnimTransformer
|
||||||
import org.koitharu.kotatsu.ui.reader.standard.PagerPaginationListener
|
import org.koitharu.kotatsu.ui.reader.standard.PagerPaginationListener
|
||||||
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
||||||
|
import org.koitharu.kotatsu.utils.ext.swapAdapter
|
||||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
class ReversedReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
class ReversedReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
||||||
@@ -56,6 +57,11 @@ class ReversedReaderFragment : AbstractReader(R.layout.fragment_reader_standard)
|
|||||||
return ReversedPagesAdapter(dataSet, loader)
|
return ReversedPagesAdapter(dataSet, loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun recreateAdapter() {
|
||||||
|
super.recreateAdapter()
|
||||||
|
pager.swapAdapter(adapter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getCurrentItem() = reversed(pager.currentItem)
|
override fun getCurrentItem() = reversed(pager.currentItem)
|
||||||
|
|
||||||
override fun setCurrentItem(position: Int, isSmooth: Boolean) {
|
override fun setCurrentItem(position: Int, isSmooth: Boolean) {
|
||||||
|
|||||||
@@ -1,19 +1,22 @@
|
|||||||
package org.koitharu.kotatsu.ui.reader.standard
|
package org.koitharu.kotatsu.ui.reader.standard
|
||||||
|
|
||||||
|
import android.graphics.PointF
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.view.isVisible
|
import androidx.core.view.isVisible
|
||||||
import com.davemorrissey.labs.subscaleview.ImageSource
|
import com.davemorrissey.labs.subscaleview.ImageSource
|
||||||
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import kotlinx.android.synthetic.main.item_page.*
|
import kotlinx.android.synthetic.main.item_page.*
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||||
import org.koitharu.kotatsu.ui.reader.PageLoader
|
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||||
import org.koitharu.kotatsu.ui.reader.base.PageHolderDelegate
|
import org.koitharu.kotatsu.ui.reader.base.PageHolderDelegate
|
||||||
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
||||||
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
import org.koitharu.kotatsu.utils.ext.getDisplayMessage
|
||||||
|
|
||||||
class PageHolder(parent: ViewGroup, loader: PageLoader) :
|
open class PageHolder(parent: ViewGroup, loader: PageLoader) :
|
||||||
BaseViewHolder<ReaderPage, Unit>(parent, R.layout.item_page),
|
BaseViewHolder<ReaderPage, Unit>(parent, R.layout.item_page),
|
||||||
PageHolderDelegate.Callback, View.OnClickListener {
|
PageHolderDelegate.Callback, View.OnClickListener {
|
||||||
|
|
||||||
@@ -43,13 +46,41 @@ class PageHolder(parent: ViewGroup, loader: PageLoader) :
|
|||||||
ssiv.setImage(ImageSource.uri(uri))
|
ssiv.setImage(ImageSource.uri(uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onImageShowing() {
|
override fun onImageShowing(zoom: ZoomMode) {
|
||||||
ssiv.maxScale = 2f * maxOf(
|
ssiv.maxScale = 2f * maxOf(
|
||||||
ssiv.width / ssiv.sWidth.toFloat(),
|
ssiv.width / ssiv.sWidth.toFloat(),
|
||||||
ssiv.height / ssiv.sHeight.toFloat()
|
ssiv.height / ssiv.sHeight.toFloat()
|
||||||
)
|
)
|
||||||
|
when (zoom) {
|
||||||
|
ZoomMode.FIT_CENTER -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE)
|
||||||
ssiv.resetScaleAndCenter()
|
ssiv.resetScaleAndCenter()
|
||||||
}
|
}
|
||||||
|
ZoomMode.FIT_HEIGHT -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
||||||
|
ssiv.minScale = ssiv.height / ssiv.sHeight.toFloat()
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.minScale,
|
||||||
|
PointF(0f, ssiv.sHeight / 2f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ZoomMode.FIT_WIDTH -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
||||||
|
ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat()
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.minScale,
|
||||||
|
PointF(ssiv.sWidth / 2f, 0f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
ZoomMode.KEEP_START -> {
|
||||||
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE)
|
||||||
|
ssiv.setScaleAndCenter(
|
||||||
|
ssiv.maxScale,
|
||||||
|
PointF(0f, 0f)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onImageShown() {
|
override fun onImageShown() {
|
||||||
progressBar.isVisible = false
|
progressBar.isVisible = false
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.koitharu.kotatsu.ui.reader.base.AbstractReader
|
|||||||
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
import org.koitharu.kotatsu.ui.reader.base.BaseReaderAdapter
|
||||||
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
import org.koitharu.kotatsu.ui.reader.base.ReaderPage
|
||||||
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
import org.koitharu.kotatsu.utils.ext.doOnPageChanged
|
||||||
|
import org.koitharu.kotatsu.utils.ext.swapAdapter
|
||||||
import org.koitharu.kotatsu.utils.ext.withArgs
|
import org.koitharu.kotatsu.utils.ext.withArgs
|
||||||
|
|
||||||
class PagerReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
class PagerReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
||||||
@@ -52,6 +53,11 @@ class PagerReaderFragment : AbstractReader(R.layout.fragment_reader_standard),
|
|||||||
return PagesAdapter(dataSet, loader)
|
return PagesAdapter(dataSet, loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun recreateAdapter() {
|
||||||
|
super.recreateAdapter()
|
||||||
|
pager.swapAdapter(adapter)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getCurrentItem() = pager.currentItem
|
override fun getCurrentItem() = pager.currentItem
|
||||||
|
|
||||||
override fun setCurrentItem(position: Int, isSmooth: Boolean) {
|
override fun setCurrentItem(position: Int, isSmooth: Boolean) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import com.davemorrissey.labs.subscaleview.ImageSource
|
|||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
|
||||||
import kotlinx.android.synthetic.main.item_page_webtoon.*
|
import kotlinx.android.synthetic.main.item_page_webtoon.*
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
import org.koitharu.kotatsu.ui.base.list.BaseViewHolder
|
||||||
import org.koitharu.kotatsu.ui.reader.PageLoader
|
import org.koitharu.kotatsu.ui.reader.PageLoader
|
||||||
import org.koitharu.kotatsu.ui.reader.base.PageHolderDelegate
|
import org.koitharu.kotatsu.ui.reader.base.PageHolderDelegate
|
||||||
@@ -46,7 +47,7 @@ class WebtoonHolder(parent: ViewGroup, private val loader: PageLoader) :
|
|||||||
ssiv.setImage(ImageSource.uri(uri))
|
ssiv.setImage(ImageSource.uri(uri))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onImageShowing() {
|
override fun onImageShowing(zoom: ZoomMode) {
|
||||||
ssiv.maxScale = 2f * ssiv.width / ssiv.sWidth.toFloat()
|
ssiv.maxScale = 2f * ssiv.width / ssiv.sWidth.toFloat()
|
||||||
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
ssiv.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CUSTOM)
|
||||||
ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat()
|
ssiv.minScale = ssiv.width / ssiv.sWidth.toFloat()
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ class WebtoonReaderFragment : AbstractReader(R.layout.fragment_reader_webtoon) {
|
|||||||
return WebtoonAdapter(dataSet, loader)
|
return WebtoonAdapter(dataSet, loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun recreateAdapter() {
|
||||||
|
super.recreateAdapter()
|
||||||
|
recyclerView.swapAdapter(adapter, true)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
paginationListener = null
|
paginationListener = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import kotlinx.coroutines.launch
|
|||||||
import org.koitharu.kotatsu.BuildConfig
|
import org.koitharu.kotatsu.BuildConfig
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.core.model.MangaSource
|
import org.koitharu.kotatsu.core.model.MangaSource
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.core.prefs.ListMode
|
import org.koitharu.kotatsu.core.prefs.ListMode
|
||||||
import org.koitharu.kotatsu.ui.base.BasePreferenceFragment
|
import org.koitharu.kotatsu.ui.base.BasePreferenceFragment
|
||||||
@@ -26,6 +27,7 @@ import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
|
|||||||
import org.koitharu.kotatsu.ui.tracker.TrackWorker
|
import org.koitharu.kotatsu.ui.tracker.TrackWorker
|
||||||
import org.koitharu.kotatsu.utils.ext.getStorageName
|
import org.koitharu.kotatsu.utils.ext.getStorageName
|
||||||
import org.koitharu.kotatsu.utils.ext.md5
|
import org.koitharu.kotatsu.utils.ext.md5
|
||||||
|
import org.koitharu.kotatsu.utils.ext.names
|
||||||
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -60,6 +62,11 @@ class MainSettingsFragment : BasePreferenceFragment(R.string.settings),
|
|||||||
summary = settings.getStorageDir(context)?.getStorageName(context)
|
summary = settings.getStorageDir(context)?.getStorageName(context)
|
||||||
?: getString(R.string.not_available)
|
?: getString(R.string.not_available)
|
||||||
}
|
}
|
||||||
|
findPreference<ListPreference>(AppSettings.KEY_ZOOM_MODE)?.let {
|
||||||
|
it.entryValues = ZoomMode.values().names()
|
||||||
|
it.setDefaultValue(ZoomMode.FIT_CENTER.name)
|
||||||
|
it.summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
|
||||||
|
}
|
||||||
findPreference<SwitchPreference>(AppSettings.KEY_PROTECT_APP)?.isChecked =
|
findPreference<SwitchPreference>(AppSettings.KEY_PROTECT_APP)?.isChecked =
|
||||||
!settings.appPassword.isNullOrEmpty()
|
!settings.appPassword.isNullOrEmpty()
|
||||||
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
findPreference<Preference>(AppSettings.KEY_APP_VERSION)?.run {
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ package org.koitharu.kotatsu.ui.settings
|
|||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.MultiSelectListPreference
|
import androidx.preference.MultiSelectListPreference
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.model.ZoomMode
|
||||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
import org.koitharu.kotatsu.ui.base.BasePreferenceFragment
|
import org.koitharu.kotatsu.ui.base.BasePreferenceFragment
|
||||||
import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
|
import org.koitharu.kotatsu.ui.settings.utils.MultiSummaryProvider
|
||||||
|
import org.koitharu.kotatsu.utils.ext.names
|
||||||
|
|
||||||
class ReaderSettingsFragment : BasePreferenceFragment(R.string.reader_settings) {
|
class ReaderSettingsFragment : BasePreferenceFragment(R.string.reader_settings) {
|
||||||
|
|
||||||
@@ -19,5 +22,10 @@ class ReaderSettingsFragment : BasePreferenceFragment(R.string.reader_settings)
|
|||||||
findPreference<MultiSelectListPreference>(AppSettings.KEY_READER_SWITCHERS)?.let {
|
findPreference<MultiSelectListPreference>(AppSettings.KEY_READER_SWITCHERS)?.let {
|
||||||
it.summaryProvider = MultiSummaryProvider(R.string.gestures_only)
|
it.summaryProvider = MultiSummaryProvider(R.string.gestures_only)
|
||||||
}
|
}
|
||||||
|
findPreference<ListPreference>(AppSettings.KEY_ZOOM_MODE)?.let {
|
||||||
|
it.entryValues = ZoomMode.values().names()
|
||||||
|
it.setDefaultValue(ZoomMode.FIT_CENTER.name)
|
||||||
|
it.summaryProvider = ListPreference.SimpleSummaryProvider.getInstance()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,20 +9,19 @@ class EnumPreferenceDelegate<E : Enum<*>>(
|
|||||||
private val cls: Class<E>,
|
private val cls: Class<E>,
|
||||||
private val key: String,
|
private val key: String,
|
||||||
private val defValue: E
|
private val defValue: E
|
||||||
) :
|
) : ReadWriteProperty<SharedPreferences, E> {
|
||||||
ReadWriteProperty<SharedPreferences, E> {
|
|
||||||
|
|
||||||
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): E {
|
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): E {
|
||||||
val ord = thisRef.getInt(key, -1)
|
val name = thisRef.getString(key, null)
|
||||||
if (ord == -1) {
|
if (name === null) {
|
||||||
return defValue
|
return defValue
|
||||||
}
|
}
|
||||||
return cls.enumConstants?.firstOrNull { it.ordinal == ord } ?: defValue
|
return cls.enumConstants?.find { it.name == name } ?: defValue
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: E) {
|
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: E) {
|
||||||
thisRef.edit {
|
thisRef.edit {
|
||||||
putInt(key, value.ordinal)
|
putString(key, value.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package org.koitharu.kotatsu.utils.delegates.prefs
|
||||||
|
|
||||||
|
import android.content.SharedPreferences
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import kotlin.properties.ReadWriteProperty
|
||||||
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
|
@Deprecated("")
|
||||||
|
class IntEnumPreferenceDelegate<E : Enum<*>>(
|
||||||
|
private val cls: Class<E>,
|
||||||
|
private val key: String,
|
||||||
|
private val defValue: E
|
||||||
|
) : ReadWriteProperty<SharedPreferences, E> {
|
||||||
|
|
||||||
|
override fun getValue(thisRef: SharedPreferences, property: KProperty<*>): E {
|
||||||
|
val ord = thisRef.getInt(key, -1)
|
||||||
|
if (ord == -1) {
|
||||||
|
return defValue
|
||||||
|
}
|
||||||
|
return cls.enumConstants?.getOrNull(ord) ?: defValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setValue(thisRef: SharedPreferences, property: KProperty<*>, value: E) {
|
||||||
|
thisRef.edit {
|
||||||
|
putInt(key, value.ordinal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,3 +67,9 @@ inline fun <T> Collection<T>.associateByLong(selector: (T) -> Long): LongSparseA
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline fun <T, reified R> Array<T>.mapToArray(transform: (T) -> R): Array<R> = Array(size) { i ->
|
||||||
|
transform(get(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T : Enum<T>> Array<T>.names() = mapToArray { it.name }
|
||||||
@@ -201,3 +201,11 @@ fun RecyclerView.findCenterViewPosition(): Int {
|
|||||||
val view = findChildViewUnder(centerX, centerY) ?: return RecyclerView.NO_POSITION
|
val view = findChildViewUnder(centerX, centerY) ?: return RecyclerView.NO_POSITION
|
||||||
return getChildAdapterPosition(view)
|
return getChildAdapterPosition(view)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun ViewPager2.swapAdapter(newAdapter: RecyclerView.Adapter<*>?) {
|
||||||
|
val position = currentItem
|
||||||
|
adapter = newAdapter
|
||||||
|
if (adapter != null && position != RecyclerView.NO_POSITION) {
|
||||||
|
currentItem = position
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -163,4 +163,9 @@
|
|||||||
<string name="prefer_rtl_reader">Предпочитать режим Справа налево</string>
|
<string name="prefer_rtl_reader">Предпочитать режим Справа налево</string>
|
||||||
<string name="prefer_rtl_reader_summary">Вы можете настроить режим чтения для каждой манги отдельно</string>
|
<string name="prefer_rtl_reader_summary">Вы можете настроить режим чтения для каждой манги отдельно</string>
|
||||||
<string name="create_category">Создать категорию</string>
|
<string name="create_category">Создать категорию</string>
|
||||||
|
<string name="scale_mode">Масштабирование</string>
|
||||||
|
<string name="zoom_mode_fit_center">Вписать в экран</string>
|
||||||
|
<string name="zoom_mode_fit_height">Подогнать по высоте</string>
|
||||||
|
<string name="zoom_mode_fit_width">Подогнать по ширине</string>
|
||||||
|
<string name="zoom_mode_keep_start">Исходный размер</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -9,6 +9,12 @@
|
|||||||
<item>@string/taps_on_edges</item>
|
<item>@string/taps_on_edges</item>
|
||||||
<item>@string/volume_buttons</item>
|
<item>@string/volume_buttons</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="zoom_modes">
|
||||||
|
<item>@string/zoom_mode_fit_center</item>
|
||||||
|
<item>@string/zoom_mode_fit_height</item>
|
||||||
|
<item>@string/zoom_mode_fit_width</item>
|
||||||
|
<item>@string/zoom_mode_keep_start</item>
|
||||||
|
</string-array>
|
||||||
<string-array name="track_sources">
|
<string-array name="track_sources">
|
||||||
<item>@string/favourites</item>
|
<item>@string/favourites</item>
|
||||||
<item>@string/history</item>
|
<item>@string/history</item>
|
||||||
|
|||||||
@@ -165,4 +165,9 @@
|
|||||||
<string name="prefer_rtl_reader_summary">You can set up the reading mode for each manga separately</string>
|
<string name="prefer_rtl_reader_summary">You can set up the reading mode for each manga separately</string>
|
||||||
<string name="create_category">New category</string>
|
<string name="create_category">New category</string>
|
||||||
<string name="report_github">Create issue on GitHub</string>
|
<string name="report_github">Create issue on GitHub</string>
|
||||||
|
<string name="scale_mode">Scale mode</string>
|
||||||
|
<string name="zoom_mode_fit_center">Fit center</string>
|
||||||
|
<string name="zoom_mode_fit_height">Fit to height</string>
|
||||||
|
<string name="zoom_mode_fit_width">Fit to width</string>
|
||||||
|
<string name="zoom_mode_keep_start">Keep at start</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -70,6 +70,12 @@
|
|||||||
android:title="@string/pages_animation"
|
android:title="@string/pages_animation"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/zoom_modes"
|
||||||
|
android:key="zoom_mode"
|
||||||
|
android:title="@string/scale_mode"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="reader_prefer_rtl"
|
android:key="reader_prefer_rtl"
|
||||||
|
|||||||
@@ -17,6 +17,12 @@
|
|||||||
android:title="@string/pages_animation"
|
android:title="@string/pages_animation"
|
||||||
app:iconSpaceReserved="false" />
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
|
<ListPreference
|
||||||
|
android:entries="@array/zoom_modes"
|
||||||
|
android:key="zoom_mode"
|
||||||
|
android:title="@string/scale_mode"
|
||||||
|
app:iconSpaceReserved="false" />
|
||||||
|
|
||||||
<SwitchPreference
|
<SwitchPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="reader_prefer_rtl"
|
android:key="reader_prefer_rtl"
|
||||||
|
|||||||
Reference in New Issue
Block a user