Initial commit
This commit is contained in:
commit
21bfbfb139
520 changed files with 47819 additions and 0 deletions
|
@ -0,0 +1,435 @@
|
|||
package ani.dantotsu.media.novel.novelreader
|
||||
|
||||
import android.animation.ObjectAnimator
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.pm.ActivityInfo
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.util.Base64
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.view.animation.OvershootInterpolator
|
||||
import android.widget.AdapterView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.net.toUri
|
||||
import androidx.core.view.GestureDetectorCompat
|
||||
import androidx.core.view.updateLayoutParams
|
||||
import androidx.lifecycle.lifecycleScope
|
||||
import ani.dantotsu.GesturesListener
|
||||
import ani.dantotsu.NoPaddingArrayAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.ActivityNovelReaderBinding
|
||||
import ani.dantotsu.hideSystemBars
|
||||
import ani.dantotsu.loadData
|
||||
import ani.dantotsu.others.ImageViewDialog
|
||||
import ani.dantotsu.saveData
|
||||
import ani.dantotsu.setSafeOnClickListener
|
||||
import ani.dantotsu.settings.CurrentNovelReaderSettings
|
||||
import ani.dantotsu.settings.CurrentReaderSettings
|
||||
import ani.dantotsu.settings.NovelReaderSettings
|
||||
import ani.dantotsu.settings.UserInterfaceSettings
|
||||
import ani.dantotsu.snackString
|
||||
import ani.dantotsu.tryWith
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.vipulog.ebookreader.Book
|
||||
import com.vipulog.ebookreader.EbookReaderEventListener
|
||||
import com.vipulog.ebookreader.ReaderError
|
||||
import com.vipulog.ebookreader.ReaderFlow
|
||||
import com.vipulog.ebookreader.ReaderTheme
|
||||
import com.vipulog.ebookreader.RelocationInfo
|
||||
import com.vipulog.ebookreader.TocItem
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
import kotlin.math.min
|
||||
import kotlin.properties.Delegates
|
||||
|
||||
|
||||
class NovelReaderActivity : AppCompatActivity(), EbookReaderEventListener {
|
||||
private lateinit var binding: ActivityNovelReaderBinding
|
||||
private val scope = lifecycleScope
|
||||
|
||||
lateinit var settings: NovelReaderSettings
|
||||
private lateinit var uiSettings: UserInterfaceSettings
|
||||
|
||||
private var notchHeight: Int? = null
|
||||
|
||||
var loaded = false
|
||||
|
||||
private lateinit var book: Book
|
||||
private lateinit var sanitizedBookId: String
|
||||
private lateinit var toc: List<TocItem>
|
||||
private var currentTheme: ReaderTheme? = null
|
||||
private var currentCfi: String? = null
|
||||
|
||||
val themes = ArrayList<ReaderTheme>()
|
||||
|
||||
|
||||
init {
|
||||
val forestTheme = ReaderTheme(
|
||||
name = "Forest",
|
||||
lightFg = Color.parseColor("#000000"),
|
||||
lightBg = Color.parseColor("#E7F6E7"),
|
||||
lightLink = Color.parseColor("#008000"),
|
||||
darkFg = Color.parseColor("#FFFFFF"),
|
||||
darkBg = Color.parseColor("#084D08"),
|
||||
darkLink = Color.parseColor("#00B200")
|
||||
)
|
||||
|
||||
val oceanTheme = ReaderTheme(
|
||||
name = "Ocean",
|
||||
lightFg = Color.parseColor("#000000"),
|
||||
lightBg = Color.parseColor("#E4F0F9"),
|
||||
lightLink = Color.parseColor("#007BFF"),
|
||||
darkFg = Color.parseColor("#FFFFFF"),
|
||||
darkBg = Color.parseColor("#0A2E3E"),
|
||||
darkLink = Color.parseColor("#00A5E4")
|
||||
)
|
||||
|
||||
val sunsetTheme = ReaderTheme(
|
||||
name = "Sunset",
|
||||
lightFg = Color.parseColor("#000000"),
|
||||
lightBg = Color.parseColor("#FDEDE6"),
|
||||
lightLink = Color.parseColor("#FF5733"),
|
||||
darkFg = Color.parseColor("#FFFFFF"),
|
||||
darkBg = Color.parseColor("#441517"),
|
||||
darkLink = Color.parseColor("#FF6B47")
|
||||
)
|
||||
|
||||
val desertTheme = ReaderTheme(
|
||||
name = "Desert",
|
||||
lightFg = Color.parseColor("#000000"),
|
||||
lightBg = Color.parseColor("#FDF5E6"),
|
||||
lightLink = Color.parseColor("#FFA500"),
|
||||
darkFg = Color.parseColor("#FFFFFF"),
|
||||
darkBg = Color.parseColor("#523B19"),
|
||||
darkLink = Color.parseColor("#FFBF00")
|
||||
)
|
||||
|
||||
val galaxyTheme = ReaderTheme(
|
||||
name = "Galaxy",
|
||||
lightFg = Color.parseColor("#000000"),
|
||||
lightBg = Color.parseColor("#F2F2F2"),
|
||||
lightLink = Color.parseColor("#800080"),
|
||||
darkFg = Color.parseColor("#FFFFFF"),
|
||||
darkBg = Color.parseColor("#000000"),
|
||||
darkLink = Color.parseColor("#B300B3")
|
||||
)
|
||||
|
||||
themes.addAll(listOf(forestTheme, oceanTheme, sunsetTheme, desertTheme, galaxyTheme))
|
||||
}
|
||||
|
||||
|
||||
override fun onAttachedToWindow() {
|
||||
checkNotch()
|
||||
super.onAttachedToWindow()
|
||||
}
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
binding = ActivityNovelReaderBinding.inflate(layoutInflater)
|
||||
setContentView(binding.root)
|
||||
|
||||
settings = loadData("novel_reader_settings", this)
|
||||
?: NovelReaderSettings().apply { saveData("novel_reader_settings", this) }
|
||||
uiSettings = loadData("ui_settings", this)
|
||||
?: UserInterfaceSettings().also { saveData("ui_settings", it) }
|
||||
|
||||
controllerDuration = (uiSettings.animationSpeed * 200).toLong()
|
||||
|
||||
setupViews()
|
||||
setupBackPressedHandler()
|
||||
}
|
||||
|
||||
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
private fun setupViews() {
|
||||
scope.launch { binding.bookReader.openBook(intent.data!!) }
|
||||
binding.bookReader.setEbookReaderListener(this)
|
||||
|
||||
binding.novelReaderBack.setOnClickListener { finish() }
|
||||
binding.novelReaderSettings.setSafeOnClickListener {
|
||||
NovelReaderSettingsDialogFragment.newInstance().show(supportFragmentManager, NovelReaderSettingsDialogFragment.TAG)
|
||||
}
|
||||
|
||||
val gestureDetector = GestureDetectorCompat(this, object : GesturesListener() {
|
||||
override fun onSingleClick(event: MotionEvent) {
|
||||
handleController()
|
||||
}
|
||||
})
|
||||
|
||||
binding.bookReader.setOnTouchListener { _, event ->
|
||||
if (event != null) tryWith { gestureDetector.onTouchEvent(event) } ?: false
|
||||
else false
|
||||
}
|
||||
|
||||
binding.novelReaderNextChap.setOnClickListener { binding.novelReaderNextChapter.performClick() }
|
||||
binding.novelReaderNextChapter.setOnClickListener { binding.bookReader.next() }
|
||||
binding.novelReaderPrevChap.setOnClickListener { binding.novelReaderPreviousChapter.performClick() }
|
||||
binding.novelReaderPreviousChapter.setOnClickListener { binding.bookReader.prev() }
|
||||
|
||||
binding.novelReaderSlider.addOnSliderTouchListener(object : Slider.OnSliderTouchListener {
|
||||
override fun onStartTrackingTouch(slider: Slider) {
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(slider: Slider) {
|
||||
binding.bookReader.gotoFraction(slider.value.toDouble())
|
||||
}
|
||||
})
|
||||
|
||||
onVolumeUp = { binding.novelReaderNextChapter.performClick() }
|
||||
|
||||
onVolumeDown = { binding.novelReaderPreviousChapter.performClick() }
|
||||
}
|
||||
|
||||
private fun setupBackPressedHandler() {
|
||||
var lastBackPressedTime: Long = 0
|
||||
val doublePressInterval: Long = 2000
|
||||
|
||||
onBackPressedDispatcher.addCallback(object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
if (binding.bookReader.canGoBack()) {
|
||||
binding.bookReader.goBack()
|
||||
} else {
|
||||
if (lastBackPressedTime + doublePressInterval > System.currentTimeMillis()) {
|
||||
finish()
|
||||
} else {
|
||||
snackString("Press back again to exit")
|
||||
lastBackPressedTime = System.currentTimeMillis()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
override fun onBookLoadFailed(error: ReaderError) {
|
||||
snackString(error.message)
|
||||
finish()
|
||||
}
|
||||
|
||||
|
||||
override fun onBookLoaded(book: Book) {
|
||||
this.book = book
|
||||
val bookId = book.identifier!!
|
||||
toc = book.toc
|
||||
|
||||
val illegalCharsRegex = Regex("[^a-zA-Z0-9._-]")
|
||||
sanitizedBookId = bookId.replace(illegalCharsRegex, "_")
|
||||
|
||||
binding.novelReaderTitle.text = book.title
|
||||
binding.novelReaderSource.text = book.author?.joinToString(", ")
|
||||
|
||||
val tocLabels = book.toc.map { it.label ?: "" }
|
||||
binding.novelReaderChapterSelect.adapter = NoPaddingArrayAdapter(this, R.layout.item_dropdown, tocLabels)
|
||||
binding.novelReaderChapterSelect.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
binding.bookReader.goto(book.toc[position].href)
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
binding.bookReader.getAppearance {
|
||||
currentTheme = it
|
||||
themes.add(0, it)
|
||||
settings.default = loadData("${sanitizedBookId}_current_settings") ?: settings.default
|
||||
applySettings()
|
||||
}
|
||||
|
||||
val cfi = loadData<String>("${sanitizedBookId}_progress")
|
||||
|
||||
cfi?.let { binding.bookReader.goto(it) }
|
||||
binding.progress.visibility = View.GONE
|
||||
loaded = true
|
||||
}
|
||||
|
||||
|
||||
override fun onProgressChanged(info: RelocationInfo) {
|
||||
currentCfi = info.cfi
|
||||
binding.novelReaderSlider.value = info.fraction.toFloat()
|
||||
val pos = info.tocItem?.let { item -> toc.indexOfFirst { it == item } }
|
||||
if (pos != null) binding.novelReaderChapterSelect.setSelection(pos)
|
||||
saveData("${sanitizedBookId}_progress", info.cfi)
|
||||
}
|
||||
|
||||
|
||||
override fun onImageSelected(base64String: String) {
|
||||
scope.launch(Dispatchers.IO) {
|
||||
val base64Data = base64String.substringAfter(",")
|
||||
val imageBytes: ByteArray = Base64.decode(base64Data, Base64.DEFAULT)
|
||||
val imageFile = File(cacheDir, "/images/ln.jpg")
|
||||
|
||||
imageFile.parentFile?.mkdirs()
|
||||
imageFile.createNewFile()
|
||||
|
||||
FileOutputStream(imageFile).use { outputStream -> outputStream.write(imageBytes) }
|
||||
|
||||
ImageViewDialog.newInstance(
|
||||
this@NovelReaderActivity,
|
||||
book.title,
|
||||
imageFile.toUri().toString()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onTextSelectionModeChange(mode: Boolean) {
|
||||
// TODO: Show ui for adding annotations and notes
|
||||
}
|
||||
|
||||
|
||||
private var onVolumeUp: (() -> Unit)? = null
|
||||
private var onVolumeDown: (() -> Unit)? = null
|
||||
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
|
||||
return when (event.keyCode) {
|
||||
KeyEvent.KEYCODE_VOLUME_UP, KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_PAGE_UP -> {
|
||||
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_UP)
|
||||
if (!settings.default.volumeButtons)
|
||||
return false
|
||||
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
onVolumeUp?.invoke()
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
KeyEvent.KEYCODE_VOLUME_DOWN, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_PAGE_DOWN -> {
|
||||
if (event.keyCode == KeyEvent.KEYCODE_VOLUME_DOWN)
|
||||
if (!settings.default.volumeButtons)
|
||||
return false
|
||||
if (event.action == KeyEvent.ACTION_DOWN) {
|
||||
onVolumeDown?.invoke()
|
||||
true
|
||||
} else false
|
||||
}
|
||||
|
||||
else -> {
|
||||
super.dispatchKeyEvent(event)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun applySettings() {
|
||||
saveData("${sanitizedBookId}_current_settings", settings.default)
|
||||
hideBars()
|
||||
|
||||
currentTheme = themes.first { it.name.equals(settings.default.currentThemeName, ignoreCase = true) }
|
||||
|
||||
when (settings.default.layout) {
|
||||
CurrentNovelReaderSettings.Layouts.PAGED -> {
|
||||
currentTheme?.flow = ReaderFlow.PAGINATED
|
||||
}
|
||||
|
||||
CurrentNovelReaderSettings.Layouts.SCROLLED -> {
|
||||
currentTheme?.flow = ReaderFlow.SCROLLED
|
||||
}
|
||||
}
|
||||
|
||||
requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER
|
||||
when (settings.default.dualPageMode) {
|
||||
CurrentReaderSettings.DualPageModes.No -> currentTheme?.maxColumnCount = 1
|
||||
CurrentReaderSettings.DualPageModes.Automatic -> currentTheme?.maxColumnCount = 2
|
||||
CurrentReaderSettings.DualPageModes.Force -> requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE
|
||||
}
|
||||
|
||||
currentTheme?.lineHeight = settings.default.lineHeight
|
||||
currentTheme?.gap = settings.default.margin
|
||||
currentTheme?.maxInlineSize = settings.default.maxInlineSize
|
||||
currentTheme?.maxBlockSize = settings.default.maxBlockSize
|
||||
currentTheme?.useDark = settings.default.useDarkTheme
|
||||
|
||||
currentTheme?.let { binding.bookReader.setAppearance(it) }
|
||||
|
||||
if (settings.default.keepScreenOn) window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
else window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
|
||||
|
||||
// region Handle Controls
|
||||
private var isContVisible = false
|
||||
private var isAnimating = false
|
||||
private var goneTimer = Timer()
|
||||
private var controllerDuration by Delegates.notNull<Long>()
|
||||
private val overshoot = OvershootInterpolator(1.4f)
|
||||
|
||||
fun gone() {
|
||||
goneTimer.cancel()
|
||||
goneTimer.purge()
|
||||
val timerTask: TimerTask = object : TimerTask() {
|
||||
override fun run() {
|
||||
if (!isContVisible) binding.novelReaderCont.post {
|
||||
binding.novelReaderCont.visibility = View.GONE
|
||||
isAnimating = false
|
||||
}
|
||||
}
|
||||
}
|
||||
goneTimer = Timer()
|
||||
goneTimer.schedule(timerTask, controllerDuration)
|
||||
}
|
||||
|
||||
fun handleController(shouldShow: Boolean? = null) {
|
||||
if (!loaded) return
|
||||
|
||||
if (!settings.showSystemBars) {
|
||||
hideBars()
|
||||
applyNotchMargin()
|
||||
}
|
||||
|
||||
shouldShow?.apply { isContVisible = !this }
|
||||
if (isContVisible) {
|
||||
isContVisible = false
|
||||
if (!isAnimating) {
|
||||
isAnimating = true
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 1f, 0f).setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderBottomCont, "translationY", 0f, 128f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
ObjectAnimator.ofFloat(binding.novelReaderTopLayout, "translationY", 0f, -128f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
}
|
||||
gone()
|
||||
} else {
|
||||
isContVisible = true
|
||||
binding.novelReaderCont.visibility = View.VISIBLE
|
||||
ObjectAnimator.ofFloat(binding.novelReaderCont, "alpha", 0f, 1f).setDuration(controllerDuration).start()
|
||||
ObjectAnimator.ofFloat(binding.novelReaderTopLayout, "translationY", -128f, 0f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
ObjectAnimator.ofFloat(binding.novelReaderBottomCont, "translationY", 128f, 0f)
|
||||
.apply { interpolator = overshoot;duration = controllerDuration;start() }
|
||||
}
|
||||
}
|
||||
// endregion Handle Controls
|
||||
|
||||
|
||||
private fun checkNotch() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !settings.showSystemBars) {
|
||||
val displayCutout = window.decorView.rootWindowInsets.displayCutout
|
||||
if (displayCutout != null) {
|
||||
if (displayCutout.boundingRects.size > 0) {
|
||||
notchHeight = min(displayCutout.boundingRects[0].width(), displayCutout.boundingRects[0].height())
|
||||
applyNotchMargin()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun applyNotchMargin() {
|
||||
binding.novelReaderTopLayout.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||
topMargin = notchHeight ?: return
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun hideBars() {
|
||||
if (!settings.showSystemBars) hideSystemBars()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,196 @@
|
|||
package ani.dantotsu.media.novel.novelreader
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import ani.dantotsu.BottomSheetDialogFragment
|
||||
import ani.dantotsu.NoPaddingArrayAdapter
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.databinding.BottomSheetCurrentNovelReaderSettingsBinding
|
||||
import ani.dantotsu.settings.CurrentNovelReaderSettings
|
||||
import ani.dantotsu.settings.CurrentReaderSettings
|
||||
|
||||
class NovelReaderSettingsDialogFragment : BottomSheetDialogFragment() {
|
||||
private var _binding: BottomSheetCurrentNovelReaderSettingsBinding? = null
|
||||
private val binding get() = _binding!!
|
||||
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
_binding = BottomSheetCurrentNovelReaderSettingsBinding.inflate(inflater, container, false)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
val activity = requireActivity() as NovelReaderActivity
|
||||
val settings = activity.settings.default
|
||||
|
||||
val themeLabels = activity.themes.map { it.name }
|
||||
binding.themeSelect.adapter = NoPaddingArrayAdapter(activity, R.layout.item_dropdown, themeLabels)
|
||||
binding.themeSelect.setSelection(themeLabels.indexOfFirst { it == settings.currentThemeName })
|
||||
binding.themeSelect.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
|
||||
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
|
||||
settings.currentThemeName = themeLabels[position]
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
override fun onNothingSelected(parent: AdapterView<*>?) {}
|
||||
}
|
||||
|
||||
val layoutList = listOf(
|
||||
binding.paged,
|
||||
binding.continuous
|
||||
)
|
||||
|
||||
binding.layoutText.text = settings.layout.string
|
||||
var selected = layoutList[settings.layout.ordinal]
|
||||
selected.alpha = 1f
|
||||
|
||||
layoutList.forEachIndexed { index, imageButton ->
|
||||
imageButton.setOnClickListener {
|
||||
selected.alpha = 0.33f
|
||||
selected = imageButton
|
||||
selected.alpha = 1f
|
||||
settings.layout = CurrentNovelReaderSettings.Layouts[index]?:CurrentNovelReaderSettings.Layouts.PAGED
|
||||
binding.layoutText.text = settings.layout.string
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
val dualList = listOf(
|
||||
binding.dualNo,
|
||||
binding.dualAuto,
|
||||
binding.dualForce
|
||||
)
|
||||
|
||||
binding.dualPageText.text = settings.dualPageMode.toString()
|
||||
var selectedDual = dualList[settings.dualPageMode.ordinal]
|
||||
selectedDual.alpha = 1f
|
||||
|
||||
dualList.forEachIndexed { index, imageButton ->
|
||||
imageButton.setOnClickListener {
|
||||
selectedDual.alpha = 0.33f
|
||||
selectedDual = imageButton
|
||||
selectedDual.alpha = 1f
|
||||
settings.dualPageMode = CurrentReaderSettings.DualPageModes[index] ?: CurrentReaderSettings.DualPageModes.Automatic
|
||||
binding.dualPageText.text = settings.dualPageMode.toString()
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
binding.lineHeight.setText(settings.lineHeight.toString())
|
||||
binding.lineHeight.setOnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
val value = binding.lineHeight.text.toString().toFloatOrNull() ?: 1.4f
|
||||
settings.lineHeight = value
|
||||
binding.lineHeight.setText(value.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
binding.incrementLineHeight.setOnClickListener {
|
||||
val value = binding.lineHeight.text.toString().toFloatOrNull() ?: 1.4f
|
||||
settings.lineHeight = value + 0.1f
|
||||
binding.lineHeight.setText(settings.lineHeight.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.decrementLineHeight.setOnClickListener {
|
||||
val value = binding.lineHeight.text.toString().toFloatOrNull() ?: 1.4f
|
||||
settings.lineHeight = value - 0.1f
|
||||
binding.lineHeight.setText(settings.lineHeight.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.margin.setText(settings.margin.toString())
|
||||
binding.margin.setOnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
val value = binding.margin.text.toString().toFloatOrNull() ?: 0.06f
|
||||
settings.margin = value
|
||||
binding.margin.setText(value.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
binding.incrementMargin.setOnClickListener {
|
||||
val value = binding.margin.text.toString().toFloatOrNull() ?: 0.06f
|
||||
settings.margin = value + 0.01f
|
||||
binding.margin.setText(settings.margin.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.decrementMargin.setOnClickListener {
|
||||
val value = binding.margin.text.toString().toFloatOrNull() ?: 0.06f
|
||||
settings.margin = value - 0.01f
|
||||
binding.margin.setText(settings.margin.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.maxInlineSize.setText(settings.maxInlineSize.toString())
|
||||
binding.maxInlineSize.setOnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
val value = binding.maxInlineSize.text.toString().toIntOrNull() ?: 720
|
||||
settings.maxInlineSize = value
|
||||
binding.maxInlineSize.setText(value.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
binding.incrementMaxInlineSize.setOnClickListener {
|
||||
val value = binding.maxInlineSize.text.toString().toIntOrNull() ?: 720
|
||||
settings.maxInlineSize = value + 10
|
||||
binding.maxInlineSize.setText(settings.maxInlineSize.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.decrementMaxInlineSize.setOnClickListener {
|
||||
val value = binding.maxInlineSize.text.toString().toIntOrNull() ?: 720
|
||||
settings.maxInlineSize = value - 10
|
||||
binding.maxInlineSize.setText(settings.maxInlineSize.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.maxBlockSize.setText(settings.maxBlockSize.toString())
|
||||
binding.maxBlockSize.setOnFocusChangeListener { _, hasFocus ->
|
||||
if (!hasFocus) {
|
||||
val value = binding.maxBlockSize.text.toString().toIntOrNull() ?: 720
|
||||
settings.maxBlockSize = value
|
||||
binding.maxBlockSize.setText(value.toString())
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
binding.useDarkTheme.isChecked = settings.useDarkTheme
|
||||
binding.useDarkTheme.setOnCheckedChangeListener { _,isChecked ->
|
||||
settings.useDarkTheme = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.keepScreenOn.isChecked = settings.keepScreenOn
|
||||
binding.keepScreenOn.setOnCheckedChangeListener { _,isChecked ->
|
||||
settings.keepScreenOn = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
|
||||
binding.volumeButton.isChecked = settings.volumeButtons
|
||||
binding.volumeButton.setOnCheckedChangeListener { _,isChecked ->
|
||||
settings.volumeButtons = isChecked
|
||||
activity.applySettings()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onDestroy() {
|
||||
_binding = null
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
|
||||
companion object{
|
||||
fun newInstance() = NovelReaderSettingsDialogFragment()
|
||||
const val TAG = "NovelReaderSettingsDialogFragment"
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue