mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-25 14:19:27 +03:00
Merge branch 'pr8'
This commit is contained in:
commit
2e9357c53e
14 changed files with 288 additions and 127 deletions
|
@ -2,14 +2,20 @@ package eu.kanade.tachiyomi
|
||||||
|
|
||||||
import android.app.ActivityManager
|
import android.app.ActivityManager
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import android.app.PendingIntent
|
||||||
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.content.getSystemService
|
import androidx.core.content.getSystemService
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.LifecycleObserver
|
import androidx.lifecycle.LifecycleObserver
|
||||||
import androidx.lifecycle.OnLifecycleEvent
|
import androidx.lifecycle.OnLifecycleEvent
|
||||||
import androidx.lifecycle.ProcessLifecycleOwner
|
import androidx.lifecycle.ProcessLifecycleOwner
|
||||||
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.multidex.MultiDex
|
import androidx.multidex.MultiDex
|
||||||
import coil.ImageLoader
|
import coil.ImageLoader
|
||||||
import coil.ImageLoaderFactory
|
import coil.ImageLoaderFactory
|
||||||
|
@ -22,6 +28,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate
|
||||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||||
|
import eu.kanade.tachiyomi.util.system.notification
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
import org.acra.ACRA
|
import org.acra.ACRA
|
||||||
import org.acra.annotation.AcraCore
|
import org.acra.annotation.AcraCore
|
||||||
import org.acra.annotation.AcraHttpSender
|
import org.acra.annotation.AcraHttpSender
|
||||||
|
@ -45,6 +54,8 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
|
private val disableIncognitoReceiver = DisableIncognitoReceiver()
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
if (BuildConfig.DEBUG) Timber.plant(Timber.DebugTree())
|
||||||
|
@ -65,6 +76,34 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
||||||
|
|
||||||
// Reset Incognito Mode on relaunch
|
// Reset Incognito Mode on relaunch
|
||||||
preferences.incognitoMode().set(false)
|
preferences.incognitoMode().set(false)
|
||||||
|
|
||||||
|
// Show notification to disable Incognito Mode when it's enabled
|
||||||
|
preferences.incognitoMode().asFlow()
|
||||||
|
.onEach { enabled ->
|
||||||
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
|
if (enabled) {
|
||||||
|
disableIncognitoReceiver.register()
|
||||||
|
val notification = notification(Notifications.CHANNEL_INCOGNITO_MODE) {
|
||||||
|
setContentTitle(getString(R.string.pref_incognito_mode))
|
||||||
|
setContentText(getString(R.string.notification_incognito_text))
|
||||||
|
setSmallIcon(R.drawable.ic_glasses_black_24dp)
|
||||||
|
setOngoing(true)
|
||||||
|
|
||||||
|
val pendingIntent = PendingIntent.getBroadcast(
|
||||||
|
this@App,
|
||||||
|
0,
|
||||||
|
Intent(ACTION_DISABLE_INCOGNITO_MODE),
|
||||||
|
PendingIntent.FLAG_ONE_SHOT
|
||||||
|
)
|
||||||
|
setContentIntent(pendingIntent)
|
||||||
|
}
|
||||||
|
notificationManager.notify(Notifications.ID_INCOGNITO_MODE, notification)
|
||||||
|
} else {
|
||||||
|
disableIncognitoReceiver.unregister()
|
||||||
|
notificationManager.cancel(Notifications.ID_INCOGNITO_MODE)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
|
@ -111,4 +150,30 @@ open class App : Application(), LifecycleObserver, ImageLoaderFactory {
|
||||||
protected open fun setupNotificationChannels() {
|
protected open fun setupNotificationChannels() {
|
||||||
Notifications.createChannels(this)
|
Notifications.createChannels(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inner class DisableIncognitoReceiver : BroadcastReceiver() {
|
||||||
|
private var registered = false
|
||||||
|
|
||||||
|
override fun onReceive(context: Context, intent: Intent) {
|
||||||
|
preferences.incognitoMode().set(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun register() {
|
||||||
|
if (!registered) {
|
||||||
|
registerReceiver(this, IntentFilter(ACTION_DISABLE_INCOGNITO_MODE))
|
||||||
|
registered = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun unregister() {
|
||||||
|
if (registered) {
|
||||||
|
unregisterReceiver(this)
|
||||||
|
registered = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ACTION_DISABLE_INCOGNITO_MODE = "tachi.action.DISABLE_INCOGNITO_MODE"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,12 @@ object Notifications {
|
||||||
const val CHANNEL_CRASH_LOGS = "crash_logs_channel"
|
const val CHANNEL_CRASH_LOGS = "crash_logs_channel"
|
||||||
const val ID_CRASH_LOGS = -601
|
const val ID_CRASH_LOGS = -601
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification channel used for Incognito Mode
|
||||||
|
*/
|
||||||
|
const val CHANNEL_INCOGNITO_MODE = "incognito_mode_channel"
|
||||||
|
const val ID_INCOGNITO_MODE = -701
|
||||||
|
|
||||||
private val deprecatedChannels = listOf(
|
private val deprecatedChannels = listOf(
|
||||||
"downloader_channel",
|
"downloader_channel",
|
||||||
"backup_restore_complete_channel"
|
"backup_restore_complete_channel"
|
||||||
|
@ -157,6 +163,11 @@ object Notifications {
|
||||||
CHANNEL_CRASH_LOGS,
|
CHANNEL_CRASH_LOGS,
|
||||||
context.getString(R.string.channel_crash_logs),
|
context.getString(R.string.channel_crash_logs),
|
||||||
NotificationManager.IMPORTANCE_HIGH
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
),
|
||||||
|
NotificationChannel(
|
||||||
|
CHANNEL_INCOGNITO_MODE,
|
||||||
|
context.getString(R.string.pref_incognito_mode),
|
||||||
|
NotificationManager.IMPORTANCE_LOW
|
||||||
)
|
)
|
||||||
).forEach(context.notificationManager::createNotificationChannel)
|
).forEach(context.notificationManager::createNotificationChannel)
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ object PreferenceKeys {
|
||||||
|
|
||||||
const val colorFilterMode = "color_filter_mode"
|
const val colorFilterMode = "color_filter_mode"
|
||||||
|
|
||||||
|
const val grayscale = "pref_grayscale"
|
||||||
|
|
||||||
const val defaultReadingMode = "pref_default_reading_mode_key"
|
const val defaultReadingMode = "pref_default_reading_mode_key"
|
||||||
|
|
||||||
const val defaultOrientationType = "pref_default_orientation_type_key"
|
const val defaultOrientationType = "pref_default_orientation_type_key"
|
||||||
|
|
|
@ -122,6 +122,8 @@ class PreferencesHelper(val context: Context) {
|
||||||
|
|
||||||
fun colorFilterMode() = flowPrefs.getInt(Keys.colorFilterMode, 0)
|
fun colorFilterMode() = flowPrefs.getInt(Keys.colorFilterMode, 0)
|
||||||
|
|
||||||
|
fun grayscale() = flowPrefs.getBoolean(Keys.grayscale, false)
|
||||||
|
|
||||||
fun defaultReadingMode() = prefs.getInt(Keys.defaultReadingMode, ReadingModeType.RIGHT_TO_LEFT.flagValue)
|
fun defaultReadingMode() = prefs.getInt(Keys.defaultReadingMode, ReadingModeType.RIGHT_TO_LEFT.flagValue)
|
||||||
|
|
||||||
fun defaultOrientationType() = prefs.getInt(Keys.defaultOrientationType, OrientationType.FREE.flagValue)
|
fun defaultOrientationType() = prefs.getInt(Keys.defaultOrientationType, OrientationType.FREE.flagValue)
|
||||||
|
|
|
@ -42,6 +42,7 @@ import eu.kanade.tachiyomi.ui.base.controller.TabbedController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
import eu.kanade.tachiyomi.ui.base.controller.ToolbarLiftOnScrollController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||||
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
import eu.kanade.tachiyomi.ui.browse.BrowseController
|
||||||
|
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceController
|
||||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
|
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
|
||||||
import eu.kanade.tachiyomi.ui.download.DownloadController
|
import eu.kanade.tachiyomi.ui.download.DownloadController
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||||
|
@ -229,7 +230,17 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
|
|
||||||
preferences.incognitoMode()
|
preferences.incognitoMode()
|
||||||
.asImmediateFlow { binding.incognitoMode.isVisible = it }
|
.asImmediateFlow {
|
||||||
|
binding.incognitoMode.isVisible = it
|
||||||
|
|
||||||
|
// Close BrowseSourceController and its MangaController child when incognito mode is disabled
|
||||||
|
if (!it) {
|
||||||
|
val fg = router.backstack.last().controller()
|
||||||
|
if (fg is BrowseSourceController || fg is MangaController && fg.fromSource) {
|
||||||
|
router.popToRoot()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ class MangaController :
|
||||||
var source: Source? = null
|
var source: Source? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
private val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false)
|
val fromSource = args.getBoolean(FROM_SOURCE_EXTRA, false)
|
||||||
|
|
||||||
private val preferences: PreferencesHelper by injectLazy()
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
private val coverCache: CoverCache by injectLazy()
|
private val coverCache: CoverCache by injectLazy()
|
||||||
|
|
|
@ -8,12 +8,16 @@ import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
|
import android.graphics.ColorMatrix
|
||||||
|
import android.graphics.ColorMatrixColorFilter
|
||||||
|
import android.graphics.Paint
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.MotionEvent
|
import android.view.MotionEvent
|
||||||
|
import android.view.View.LAYER_TYPE_HARDWARE
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.animation.Animation
|
import android.view.animation.Animation
|
||||||
import android.view.animation.AnimationUtils
|
import android.view.animation.AnimationUtils
|
||||||
|
@ -163,6 +167,12 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||||
window.decorView.setOnSystemUiVisibilityChangeListener {
|
window.decorView.setOnSystemUiVisibilityChangeListener {
|
||||||
setMenuVisibility(menuVisible, animate = false)
|
setMenuVisibility(menuVisible, animate = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Finish when incognito mode is disabled
|
||||||
|
preferences.incognitoMode().asFlow()
|
||||||
|
.drop(1)
|
||||||
|
.onEach { if (!it) finish() }
|
||||||
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -789,6 +799,16 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||||
*/
|
*/
|
||||||
private inner class ReaderConfig {
|
private inner class ReaderConfig {
|
||||||
|
|
||||||
|
private val grayscalePaint by lazy {
|
||||||
|
Paint().apply {
|
||||||
|
colorFilter = ColorMatrixColorFilter(
|
||||||
|
ColorMatrix().apply {
|
||||||
|
setSaturation(0f)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the reader subscriptions.
|
* Initializes the reader subscriptions.
|
||||||
*/
|
*/
|
||||||
|
@ -827,6 +847,10 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||||
preferences.colorFilterMode().asFlow()
|
preferences.colorFilterMode().asFlow()
|
||||||
.onEach { setColorFilter(preferences.colorFilter().get()) }
|
.onEach { setColorFilter(preferences.colorFilter().get()) }
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
|
|
||||||
|
preferences.grayscale().asFlow()
|
||||||
|
.onEach { setGrayscale(it) }
|
||||||
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -934,5 +958,10 @@ class ReaderActivity : BaseRxActivity<ReaderActivityBinding, ReaderPresenter>()
|
||||||
binding.colorOverlay.isVisible = true
|
binding.colorOverlay.isVisible = true
|
||||||
binding.colorOverlay.setFilterColor(value, preferences.colorFilterMode().get())
|
binding.colorOverlay.setFilterColor(value, preferences.colorFilterMode().get())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setGrayscale(enabled: Boolean) {
|
||||||
|
val paint = if (enabled) grayscalePaint else null
|
||||||
|
binding.viewerContainer.setLayerType(LAYER_TYPE_HARDWARE, paint)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||||
import eu.kanade.tachiyomi.ui.reader.loader.ChapterLoader
|
import eu.kanade.tachiyomi.ui.reader.loader.ChapterLoader
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.model.InsertPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
import eu.kanade.tachiyomi.ui.reader.model.ReaderPage
|
||||||
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters
|
||||||
|
@ -143,6 +144,8 @@ class ReaderPresenter(
|
||||||
hasTrackers = tracks.size > 0
|
hasTrackers = tracks.size > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val incognitoMode = preferences.incognitoMode().get()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the presenter is created. It retrieves the saved active chapter if the process
|
* Called when the presenter is created. It retrieves the saved active chapter if the process
|
||||||
* was restored.
|
* was restored.
|
||||||
|
@ -367,9 +370,14 @@ class ReaderPresenter(
|
||||||
|
|
||||||
val selectedChapter = page.chapter
|
val selectedChapter = page.chapter
|
||||||
|
|
||||||
|
// Insert page doesn't change page progress
|
||||||
|
if (page is InsertPage) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Save last page read and mark as read if needed
|
// Save last page read and mark as read if needed
|
||||||
selectedChapter.chapter.last_page_read = page.index
|
selectedChapter.chapter.last_page_read = page.index
|
||||||
val shouldTrack = !preferences.incognitoMode().get() || hasTrackers
|
val shouldTrack = !incognitoMode || hasTrackers
|
||||||
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
if (selectedChapter.pages?.lastIndex == page.index && shouldTrack) {
|
||||||
selectedChapter.chapter.read = true
|
selectedChapter.chapter.read = true
|
||||||
updateTrackChapterRead(selectedChapter)
|
updateTrackChapterRead(selectedChapter)
|
||||||
|
@ -424,7 +432,7 @@ class ReaderPresenter(
|
||||||
* If incognito mode isn't on or has at least 1 tracker
|
* If incognito mode isn't on or has at least 1 tracker
|
||||||
*/
|
*/
|
||||||
private fun saveChapterProgress(chapter: ReaderChapter) {
|
private fun saveChapterProgress(chapter: ReaderChapter) {
|
||||||
if (!preferences.incognitoMode().get() || hasTrackers) {
|
if (!incognitoMode || hasTrackers) {
|
||||||
db.updateChapterProgress(chapter.chapter).asRxCompletable()
|
db.updateChapterProgress(chapter.chapter).asRxCompletable()
|
||||||
.onErrorComplete()
|
.onErrorComplete()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -436,7 +444,7 @@ class ReaderPresenter(
|
||||||
* Saves this [chapter] last read history if incognito mode isn't on.
|
* Saves this [chapter] last read history if incognito mode isn't on.
|
||||||
*/
|
*/
|
||||||
private fun saveChapterHistory(chapter: ReaderChapter) {
|
private fun saveChapterHistory(chapter: ReaderChapter) {
|
||||||
if (!preferences.incognitoMode().get()) {
|
if (!incognitoMode) {
|
||||||
val history = History.create(chapter.chapter).apply { last_read = Date().time }
|
val history = History.create(chapter.chapter).apply { last_read = Date().time }
|
||||||
db.updateHistoryLastRead(history).asRxCompletable()
|
db.updateHistoryLastRead(history).asRxCompletable()
|
||||||
.onErrorComplete()
|
.onErrorComplete()
|
||||||
|
|
|
@ -14,7 +14,7 @@ import androidx.lifecycle.lifecycleScope
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.databinding.ReaderColorFilterSettingsBinding
|
import eu.kanade.tachiyomi.databinding.ReaderColorFilterSettingsBinding
|
||||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.widget.IgnoreFirstSpinnerListener
|
import eu.kanade.tachiyomi.util.preference.bindToPreference
|
||||||
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
import eu.kanade.tachiyomi.widget.SimpleSeekBarListener
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
@ -63,20 +63,10 @@ class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attr
|
||||||
binding.seekbarColorFilterBlue.progress = argb[3]
|
binding.seekbarColorFilterBlue.progress = argb[3]
|
||||||
|
|
||||||
// Set listeners
|
// Set listeners
|
||||||
binding.switchColorFilter.isChecked = preferences.colorFilter().get()
|
binding.switchColorFilter.bindToPreference(preferences.colorFilter())
|
||||||
binding.switchColorFilter.setOnCheckedChangeListener { _, isChecked ->
|
binding.customBrightness.bindToPreference(preferences.customBrightness())
|
||||||
preferences.colorFilter().set(isChecked)
|
binding.colorFilterMode.bindToPreference(preferences.colorFilterMode())
|
||||||
}
|
binding.grayscale.bindToPreference(preferences.grayscale())
|
||||||
|
|
||||||
binding.customBrightness.isChecked = preferences.customBrightness().get()
|
|
||||||
binding.customBrightness.setOnCheckedChangeListener { _, isChecked ->
|
|
||||||
preferences.customBrightness().set(isChecked)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.colorFilterMode.onItemSelectedListener = IgnoreFirstSpinnerListener { position ->
|
|
||||||
preferences.colorFilterMode().set(position)
|
|
||||||
}
|
|
||||||
binding.colorFilterMode.setSelection(preferences.colorFilterMode().get(), false)
|
|
||||||
|
|
||||||
binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(
|
binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(
|
||||||
object : SimpleSeekBarListener() {
|
object : SimpleSeekBarListener() {
|
||||||
|
|
|
@ -230,7 +230,7 @@ class PagerPageHolder(
|
||||||
readImageHeaderSubscription = Observable
|
readImageHeaderSubscription = Observable
|
||||||
.fromCallable {
|
.fromCallable {
|
||||||
val stream = streamFn().buffered(16)
|
val stream = streamFn().buffered(16)
|
||||||
openStream = process(stream)
|
openStream = process(item, stream)
|
||||||
|
|
||||||
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
|
ImageUtil.findImageType(stream) == ImageUtil.ImageType.GIF
|
||||||
}
|
}
|
||||||
|
@ -249,7 +249,7 @@ class PagerPageHolder(
|
||||||
.subscribe({}, {})
|
.subscribe({}, {})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun process(imageStream: InputStream): InputStream {
|
private fun process(page: ReaderPage, imageStream: InputStream): InputStream {
|
||||||
if (!viewer.config.dualPageSplit) {
|
if (!viewer.config.dualPageSplit) {
|
||||||
return imageStream
|
return imageStream
|
||||||
}
|
}
|
||||||
|
@ -263,7 +263,7 @@ class PagerPageHolder(
|
||||||
return imageStream
|
return imageStream
|
||||||
}
|
}
|
||||||
|
|
||||||
onPageSplit()
|
onPageSplit(page)
|
||||||
|
|
||||||
return splitInHalf(imageStream)
|
return splitInHalf(imageStream)
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ class PagerPageHolder(
|
||||||
return ImageUtil.splitInHalf(imageStream, side)
|
return ImageUtil.splitInHalf(imageStream, side)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onPageSplit() {
|
private fun onPageSplit(page: ReaderPage) {
|
||||||
val newPage = InsertPage(page)
|
val newPage = InsertPage(page)
|
||||||
viewer.onPageSplit(page, newPage)
|
viewer.onPageSplit(page, newPage)
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,6 +192,11 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
||||||
Timber.d("onReaderPageSelected: ${page.number}/${pages.size}")
|
Timber.d("onReaderPageSelected: ${page.number}/${pages.size}")
|
||||||
activity.onPageSelected(page)
|
activity.onPageSelected(page)
|
||||||
|
|
||||||
|
// Skip preload on inserts it causes unwanted page jumping
|
||||||
|
if (page is InsertPage) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// Preload next chapter once we're within the last 5 pages of the current chapter
|
// Preload next chapter once we're within the last 5 pages of the current chapter
|
||||||
val inPreloadRange = pages.size - page.number < 5
|
val inPreloadRange = pages.size - page.number < 5
|
||||||
if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) {
|
if (inPreloadRange && allowPreload && page.chapter == adapter.currentChapter) {
|
||||||
|
@ -387,7 +392,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
|
||||||
fun onPageSplit(currentPage: ReaderPage, newPage: InsertPage) {
|
fun onPageSplit(currentPage: ReaderPage, newPage: InsertPage) {
|
||||||
activity.runOnUiThread {
|
activity.runOnUiThread {
|
||||||
// Need to insert on UI thread else images will go blank
|
// Need to insert on UI thread else images will go blank
|
||||||
adapter.onPageSplit(currentPage, newPage, this::class.java)
|
adapter.onPageSplit(currentPage, newPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,11 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||||
var items: MutableList<Any> = mutableListOf()
|
var items: MutableList<Any> = mutableListOf()
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds preprocessed items so they don't get removed when changing chapter
|
||||||
|
*/
|
||||||
|
private var preprocessed: MutableMap<Int, InsertPage> = mutableMapOf()
|
||||||
|
|
||||||
var nextTransition: ChapterTransition.Next? = null
|
var nextTransition: ChapterTransition.Next? = null
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
@ -54,10 +59,25 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||||
newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter))
|
newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var insertPageLastPage: InsertPage? = null
|
||||||
|
|
||||||
// Add current chapter.
|
// Add current chapter.
|
||||||
val currPages = chapters.currChapter.pages
|
val currPages = chapters.currChapter.pages
|
||||||
if (currPages != null) {
|
if (currPages != null) {
|
||||||
newItems.addAll(currPages)
|
val pages = currPages.toMutableList()
|
||||||
|
|
||||||
|
val lastPage = pages.last()
|
||||||
|
|
||||||
|
// Insert preprocessed pages into current page list
|
||||||
|
preprocessed.keys.sortedDescending()
|
||||||
|
.forEach { key ->
|
||||||
|
if (lastPage.index == key) {
|
||||||
|
insertPageLastPage = preprocessed[key]
|
||||||
|
}
|
||||||
|
preprocessed[key]?.let { pages.add(key + 1, it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
newItems.addAll(pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
currentChapter = chapters.currChapter
|
currentChapter = chapters.currChapter
|
||||||
|
@ -88,8 +108,14 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||||
newItems.reverse()
|
newItems.reverse()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preprocessed = mutableMapOf()
|
||||||
items = newItems
|
items = newItems
|
||||||
notifyDataSetChanged()
|
notifyDataSetChanged()
|
||||||
|
|
||||||
|
// Will skip insert page otherwise
|
||||||
|
if (insertPageLastPage != null) {
|
||||||
|
viewer.moveToPage(insertPageLastPage!!)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -125,20 +151,25 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() {
|
||||||
return POSITION_NONE
|
return POSITION_NONE
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onPageSplit(current: Any?, newPage: InsertPage, clazz: Class<out PagerViewer>) {
|
fun onPageSplit(currentPage: Any?, newPage: InsertPage) {
|
||||||
if (current !is ReaderPage) return
|
if (currentPage !is ReaderPage) return
|
||||||
|
|
||||||
val currentIndex = items.indexOf(current)
|
val currentIndex = items.indexOf(currentPage)
|
||||||
|
|
||||||
val placeAtIndex = when {
|
// Put aside preprocessed pages for next chapter so they don't get removed when changing chapter
|
||||||
clazz.isAssignableFrom(L2RPagerViewer::class.java) -> currentIndex + 1
|
if (currentPage.chapter.chapter.id != currentChapter?.chapter?.id) {
|
||||||
clazz.isAssignableFrom(VerticalPagerViewer::class.java) -> currentIndex + 1
|
preprocessed[newPage.index] = newPage
|
||||||
clazz.isAssignableFrom(R2LPagerViewer::class.java) -> currentIndex
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val placeAtIndex = when (viewer) {
|
||||||
|
is L2RPagerViewer,
|
||||||
|
is VerticalPagerViewer -> currentIndex + 1
|
||||||
else -> currentIndex
|
else -> currentIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
// It will enter a endless cycle of insert pages
|
// It will enter a endless cycle of insert pages
|
||||||
if (clazz.isAssignableFrom(R2LPagerViewer::class.java) && items[placeAtIndex - 1] is InsertPage) {
|
if (viewer is R2LPagerViewer && placeAtIndex - 1 >= 0 && items[placeAtIndex - 1] is InsertPage) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content">
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -17,12 +16,25 @@
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/pref_custom_color_filter"
|
android:text="@string/pref_custom_color_filter"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<!-- Red filter -->
|
<!-- Red filter -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_color_filter_red_symbol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="@string/color_filter_r_value"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:id="@+id/seekbar_color_filter_red"
|
android:id="@+id/seekbar_color_filter_red"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -30,33 +42,36 @@
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:max="255"
|
android:max="255"
|
||||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
android:padding="8dp"
|
||||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_red_value"
|
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_red_value"
|
||||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||||
app:layout_constraintTop_toBottomOf="@id/switch_color_filter" />
|
app:layout_constraintTop_toBottomOf="@id/switch_color_filter" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txt_color_filter_red_symbol"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/color_filter_r_value"
|
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_color_filter_red_value"
|
android:id="@+id/txt_color_filter_red_value"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red"
|
||||||
|
tools:text="255" />
|
||||||
|
|
||||||
<!-- Green filter -->
|
<!-- Green filter -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_color_filter_green_symbol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="@string/color_filter_g_value"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:id="@+id/seekbar_color_filter_green"
|
android:id="@+id/seekbar_color_filter_green"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -64,33 +79,36 @@
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:max="255"
|
android:max="255"
|
||||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
android:padding="8dp"
|
||||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_green_value"
|
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_green_value"
|
||||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_red" />
|
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_red" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txt_color_filter_green_symbol"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/color_filter_g_value"
|
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_color_filter_green_value"
|
android:id="@+id/txt_color_filter_green_value"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green"
|
||||||
|
tools:text="255" />
|
||||||
|
|
||||||
<!-- Blue filter -->
|
<!-- Blue filter -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_color_filter_blue_symbol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/color_filter_b_value"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:id="@+id/seekbar_color_filter_blue"
|
android:id="@+id/seekbar_color_filter_blue"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -98,33 +116,36 @@
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:max="255"
|
android:max="255"
|
||||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
android:padding="8dp"
|
||||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_blue_value"
|
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_blue_value"
|
||||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_green" />
|
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_green" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txt_color_filter_blue_symbol"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/color_filter_b_value"
|
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_color_filter_blue_value"
|
android:id="@+id/txt_color_filter_blue_value"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue"
|
||||||
|
tools:text="255" />
|
||||||
|
|
||||||
<!-- Alpha filter -->
|
<!-- Alpha filter -->
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/txt_color_filter_alpha_symbol"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="@string/color_filter_a_value"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||||
|
|
||||||
<SeekBar
|
<SeekBar
|
||||||
android:id="@+id/seekbar_color_filter_alpha"
|
android:id="@+id/seekbar_color_filter_alpha"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -132,51 +153,45 @@
|
||||||
android:layout_marginStart="8dp"
|
android:layout_marginStart="8dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:max="255"
|
android:max="255"
|
||||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
android:padding="8dp"
|
||||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_alpha_value"
|
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_alpha_value"
|
||||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_blue" />
|
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_blue" />
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/txt_color_filter_alpha_symbol"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/color_filter_a_value"
|
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_color_filter_alpha_value"
|
android:id="@+id/txt_color_filter_alpha_value"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha"
|
||||||
|
tools:text="255" />
|
||||||
|
|
||||||
<!-- Filter mode -->
|
<!-- Filter mode -->
|
||||||
|
|
||||||
<TextView
|
<eu.kanade.tachiyomi.widget.MaterialSpinnerView
|
||||||
android:id="@+id/color_filter_mode_text"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/pref_color_filter_mode"
|
|
||||||
app:layout_constraintBaseline_toBaselineOf="@id/color_filter_mode"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/color_filter_mode"
|
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatSpinner
|
|
||||||
android:id="@+id/color_filter_mode"
|
android:id="@+id/color_filter_mode"
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
|
||||||
android:entries="@array/color_filter_modes"
|
android:entries="@array/color_filter_modes"
|
||||||
app:layout_constraintEnd_toStartOf="@id/spinner_end"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintStart_toEndOf="@id/verticalcenter"
|
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha" />
|
app:title="@string/pref_color_filter_mode" />
|
||||||
|
|
||||||
|
<!-- Grayscale -->
|
||||||
|
|
||||||
|
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||||
|
android:id="@+id/grayscale"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:text="@string/pref_grayscale"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/color_filter_mode" />
|
||||||
|
|
||||||
<!-- Brightness -->
|
<!-- Brightness -->
|
||||||
|
|
||||||
|
@ -185,11 +200,25 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
android:text="@string/pref_custom_brightness"
|
android:text="@string/pref_custom_brightness"
|
||||||
app:layout_constraintTop_toBottomOf="@id/color_filter_mode_text" />
|
app:layout_constraintTop_toBottomOf="@id/grayscale" />
|
||||||
|
|
||||||
<!-- Brightness value -->
|
<!-- Brightness value -->
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView
|
||||||
|
android:id="@+id/txt_brightness_seekbar_icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
|
android:tint="?attr/colorOnBackground"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||||
|
app:srcCompat="@drawable/ic_brightness_5_24dp" />
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.NegativeSeekBar
|
<eu.kanade.tachiyomi.widget.NegativeSeekBar
|
||||||
android:id="@+id/brightness_seekbar"
|
android:id="@+id/brightness_seekbar"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -203,25 +232,16 @@
|
||||||
app:max_seek="100"
|
app:max_seek="100"
|
||||||
app:min_seek="-75" />
|
app:min_seek="-75" />
|
||||||
|
|
||||||
<androidx.appcompat.widget.AppCompatImageView
|
|
||||||
android:id="@+id/txt_brightness_seekbar_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
|
||||||
android:tint="?attr/colorOnBackground"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
|
||||||
app:srcCompat="@drawable/ic_brightness_5_24dp" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/txt_brightness_seekbar_value"
|
android:id="@+id/txt_brightness_seekbar_value"
|
||||||
android:layout_width="30dp"
|
android:layout_width="30dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar" />
|
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||||
|
tools:text="50" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Barrier
|
<androidx.constraintlayout.widget.Barrier
|
||||||
android:id="@+id/color_filter_symbols_barrier"
|
android:id="@+id/color_filter_symbols_barrier"
|
||||||
|
@ -230,20 +250,6 @@
|
||||||
app:barrierDirection="end"
|
app:barrierDirection="end"
|
||||||
app:constraint_referenced_ids="txt_color_filter_alpha_symbol,txt_color_filter_blue_symbol,txt_color_filter_red_symbol,txt_color_filter_green_symbol" />
|
app:constraint_referenced_ids="txt_color_filter_alpha_symbol,txt_color_filter_blue_symbol,txt_color_filter_red_symbol,txt_color_filter_green_symbol" />
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/verticalcenter"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintGuide_percent="0.5" />
|
|
||||||
|
|
||||||
<android.widget.Space
|
|
||||||
android:id="@+id/spinner_end"
|
|
||||||
android:layout_width="16dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintStart_toEndOf="parent"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
|
|
|
@ -278,6 +278,7 @@
|
||||||
<string name="pref_true_color_summary">Reduces banding, but impacts performance</string>
|
<string name="pref_true_color_summary">Reduces banding, but impacts performance</string>
|
||||||
<string name="pref_crop_borders">Crop borders</string>
|
<string name="pref_crop_borders">Crop borders</string>
|
||||||
<string name="pref_custom_brightness">Custom brightness</string>
|
<string name="pref_custom_brightness">Custom brightness</string>
|
||||||
|
<string name="pref_grayscale">Grayscale</string>
|
||||||
<string name="pref_custom_color_filter">Custom color filter</string>
|
<string name="pref_custom_color_filter">Custom color filter</string>
|
||||||
<string name="pref_color_filter_mode">Color filter blend mode</string>
|
<string name="pref_color_filter_mode">Color filter blend mode</string>
|
||||||
<string name="filter_mode_default">Default</string>
|
<string name="filter_mode_default">Default</string>
|
||||||
|
@ -473,6 +474,7 @@
|
||||||
<string name="label_downloaded_only">Downloaded only</string>
|
<string name="label_downloaded_only">Downloaded only</string>
|
||||||
<string name="pref_incognito_mode">Incognito mode</string>
|
<string name="pref_incognito_mode">Incognito mode</string>
|
||||||
<string name="pref_incognito_mode_summary">Pauses reading history</string>
|
<string name="pref_incognito_mode_summary">Pauses reading history</string>
|
||||||
|
<string name="notification_incognito_text">Disable incognito mode</string>
|
||||||
<string name="downloaded_only_summary">Filters all manga in your library</string>
|
<string name="downloaded_only_summary">Filters all manga in your library</string>
|
||||||
<plurals name="download_queue_summary">
|
<plurals name="download_queue_summary">
|
||||||
<item quantity="one">1 remaining</item>
|
<item quantity="one">1 remaining</item>
|
||||||
|
@ -802,5 +804,4 @@
|
||||||
<!-- S Pen actions -->
|
<!-- S Pen actions -->
|
||||||
<string name="spen_previous_page">Previous page</string>
|
<string name="spen_previous_page">Previous page</string>
|
||||||
<string name="spen_next_page">Next page</string>
|
<string name="spen_next_page">Next page</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue