Reader options bs

This commit is contained in:
Koitharu
2022-07-20 15:03:17 +03:00
parent 9c94a273ea
commit f9baa4a8ad
12 changed files with 405 additions and 30 deletions

View File

@@ -6,7 +6,6 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.*
import androidx.activity.result.ActivityResultCallback
import androidx.core.graphics.Insets
import androidx.core.view.OnApplyWindowInsetsListener
import androidx.core.view.WindowInsetsCompat
@@ -36,6 +35,7 @@ import org.koitharu.kotatsu.databinding.ActivityReaderBinding
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.reader.ui.config.ReaderConfigBottomSheet
import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState
import org.koitharu.kotatsu.reader.ui.thumbnails.OnPageSelectListener
import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet
@@ -50,8 +50,7 @@ class ReaderActivity :
ChaptersBottomSheet.OnChapterChangeListener,
GridTouchHelper.OnGridTouchListener,
OnPageSelectListener,
ReaderConfigDialog.Callback,
ActivityResultCallback<Uri?>,
ReaderConfigBottomSheet.Callback,
ReaderControlDelegate.OnInteractionListener,
OnApplyWindowInsetsListener {
@@ -65,7 +64,6 @@ class ReaderActivity :
private lateinit var touchHelper: GridTouchHelper
private lateinit var controlDelegate: ReaderControlDelegate
private val savePageRequest = registerForActivityResult(PageSaveContract(), this)
private var gestureInsets: Insets = Insets.NONE
private lateinit var readerManager: ReaderManager
private val hideUiRunnable = Runnable { setUiIsVisible(false) }
@@ -116,10 +114,6 @@ class ReaderActivity :
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_menu -> {
val currentMode = readerManager.currentMode ?: return false
ReaderConfigDialog.show(supportFragmentManager, currentMode)
}
R.id.action_settings -> {
startActivity(SettingsActivity.newReaderSettingsIntent(this))
}
@@ -150,15 +144,16 @@ class ReaderActivity :
viewModel.addBookmark()
}
}
R.id.action_options -> {
viewModel.saveCurrentState(readerManager.currentReader?.getCurrentState())
val currentMode = readerManager.currentMode ?: return false
ReaderConfigBottomSheet.show(supportFragmentManager, currentMode)
}
else -> return super.onOptionsItemSelected(item)
}
return true
}
override fun onActivityResult(uri: Uri?) {
viewModel.onActivityResult(uri)
}
private fun onLoadingStateChanged(isLoading: Boolean) {
val hasPages = !viewModel.content.value?.pages.isNullOrEmpty()
binding.layoutLoading.isVisible = isLoading && !hasPages

View File

@@ -14,6 +14,7 @@ import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.databinding.DialogReaderConfigBinding
import org.koitharu.kotatsu.utils.ext.withArgs
@Deprecated("Not in use")
class ReaderConfigDialog : AlertDialogFragment<DialogReaderConfigBinding>(),
CheckableButtonGroup.OnCheckedChangeListener {
@@ -75,4 +76,4 @@ class ReaderConfigDialog : AlertDialogFragment<DialogReaderConfigBinding>(),
putInt(ARG_MODE, mode.id)
}.show(fm, TAG)
}
}
}

View File

@@ -0,0 +1,130 @@
package org.koitharu.kotatsu.reader.ui.config
import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.ActivityResultCallback
import androidx.core.view.isGone
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.flowWithLifecycle
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseBottomSheet
import org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup
import org.koitharu.kotatsu.core.prefs.ReaderMode
import org.koitharu.kotatsu.databinding.SheetReaderConfigBinding
import org.koitharu.kotatsu.reader.ui.PageSaveContract
import org.koitharu.kotatsu.reader.ui.ReaderViewModel
import org.koitharu.kotatsu.settings.SettingsActivity
import org.koitharu.kotatsu.utils.BottomSheetToolbarController
import org.koitharu.kotatsu.utils.ScreenOrientationHelper
import org.koitharu.kotatsu.utils.ext.viewLifecycleScope
import org.koitharu.kotatsu.utils.ext.withArgs
class ReaderConfigBottomSheet : BaseBottomSheet<SheetReaderConfigBinding>(),
CheckableButtonGroup.OnCheckedChangeListener,
ActivityResultCallback<Uri?>, View.OnClickListener {
private val viewModel by sharedViewModel<ReaderViewModel>()
private val savePageRequest = registerForActivityResult(PageSaveContract(), this)
private var orientationHelper: ScreenOrientationHelper? = null
private lateinit var mode: ReaderMode
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mode = arguments?.getInt(ARG_MODE)
?.let { ReaderMode.valueOf(it) }
?: ReaderMode.STANDARD
}
override fun onInflateView(inflater: LayoutInflater, container: ViewGroup?): SheetReaderConfigBinding {
return SheetReaderConfigBinding.inflate(inflater, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
observeScreenOrientation()
binding.toolbar.setNavigationOnClickListener { dismiss() }
behavior?.addBottomSheetCallback(BottomSheetToolbarController(binding.toolbar))
if (!resources.getBoolean(R.bool.is_tablet)) {
binding.toolbar.navigationIcon = null
}
binding.buttonStandard.isChecked = mode == ReaderMode.STANDARD
binding.buttonReversed.isChecked = mode == ReaderMode.REVERSED
binding.buttonWebtoon.isChecked = mode == ReaderMode.WEBTOON
binding.checkableGroup.onCheckedChangeListener = this
binding.buttonSavePage.setOnClickListener(this)
binding.buttonScreenRotate.setOnClickListener(this)
binding.buttonSettings.setOnClickListener(this)
}
override fun onClick(v: View) {
when (v.id) {
R.id.button_settings -> {
startActivity(SettingsActivity.newReaderSettingsIntent(v.context))
dismissAllowingStateLoss()
}
R.id.button_save_page -> {
val page = viewModel.getCurrentPage() ?: return
viewModel.saveCurrentPage(page, savePageRequest)
dismissAllowingStateLoss()
}
R.id.button_screen_rotate -> {
orientationHelper?.toggleOrientation()
}
}
}
override fun onCheckedChanged(group: CheckableButtonGroup, checkedId: Int) {
val newMode = when (checkedId) {
R.id.button_standard -> ReaderMode.STANDARD
R.id.button_webtoon -> ReaderMode.WEBTOON
R.id.button_reversed -> ReaderMode.REVERSED
else -> return
}
if (newMode == mode) {
return
}
findCallback()?.onReaderModeChanged(newMode) ?: return
mode = newMode
}
override fun onActivityResult(uri: Uri?) {
viewModel.onActivityResult(uri)
}
private fun observeScreenOrientation() {
val helper = ScreenOrientationHelper(requireActivity())
orientationHelper = helper
helper.observeAutoOrientation()
.flowWithLifecycle(lifecycle)
.onEach {
binding.buttonScreenRotate.isGone = it
}.launchIn(viewLifecycleScope)
}
private fun findCallback(): Callback? {
return (parentFragment as? Callback) ?: (activity as? Callback)
}
interface Callback {
fun onReaderModeChanged(mode: ReaderMode)
}
companion object {
private const val TAG = "ReaderConfigBottomSheet"
private const val ARG_MODE = "mode"
fun show(fm: FragmentManager, mode: ReaderMode) = ReaderConfigBottomSheet().withArgs(1) {
putInt(ARG_MODE, mode.id)
}.show(fm, TAG)
}
}

View File

@@ -1,11 +0,0 @@
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M4 21h15a2 2 0 0 0 2-2v-6h-4v2l-4-3 4-3v2h4V5a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2m0-6h4v2H4v-2m0-4h7v2H4v-2m0-4h7v2H4V7m17 4h3v2h-3v-2z" />
</vector>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M22,3H5A2,2 0 0,0 3,5V9H5V5H22V19H5V15H3V19A2,2 0 0,0 5,21H22A2,2 0 0,0 24,19V5A2,2 0 0,0 22,3M7,15V13H0V11H7V9L11,12L7,15M20,13H13V11H20V13M20,9H13V7H20V9M17,17H13V15H17V17Z" />
</vector>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<vector
xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:tint="?attr/colorControlNormal"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#000"
android:pathData="M2,3H19A2,2 0 0,1 21,5V9H19V5H2V19H19V15H21V19A2,2 0 0,1 19,21H2A2,2 0 0,1 0,19V5A2,2 0 0,1 2,3M17,15V13H24V11H17V9L13,12L17,15M4,13H11V11H4V13M4,9H11V7H4V9M4,17H8V15H4V17Z" />
</vector>

View File

@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<org.koitharu.kotatsu.reader.ui.ReaderToastView
android:id="@+id/toastView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|center_horizontal"
android:layout_marginBottom="20dp"
android:background="@drawable/bg_reader_indicator"
android:drawablePadding="6dp"
android:singleLine="true"
android:textAppearance="?attr/textAppearanceBodySmall"
android:theme="@style/ThemeOverlay.Material3.Dark"
tools:text="@string/loading_" />
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/dim"
android:elevation="0dp"
android:theme="@style/ThemeOverlay.Material3.Dark"
app:elevation="0dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<com.google.android.material.appbar.MaterialToolbar
android:id="@id/toolbar"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:popupTheme="@style/ThemeOverlay.Kotatsu" />
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar_bottom"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
app:menu="@menu/opt_reader_bottom"
app:popupTheme="@style/ThemeOverlay.Kotatsu">
<com.google.android.material.slider.Slider
android:id="@+id/slider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:stepSize="1"
android:valueFrom="0"
app:labelBehavior="floating"
app:tickVisible="false" />
</com.google.android.material.appbar.MaterialToolbar>
</LinearLayout>
</com.google.android.material.appbar.AppBarLayout>
<LinearLayout
android:id="@+id/layout_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center_horizontal"
android:orientation="vertical">
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
<TextView
android:id="@+id/textView_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/loading_"
android:textAppearance="?attr/textAppearanceBody2" />
</LinearLayout>
</FrameLayout>

View File

@@ -57,7 +57,6 @@
android:id="@+id/toolbar_bottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
app:menu="@menu/opt_reader_bottom"
app:popupTheme="@style/ThemeOverlay.Kotatsu">

View File

@@ -4,8 +4,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingHorizontal="16dp"
android:orientation="vertical">
android:orientation="vertical"
android:paddingHorizontal="16dp">
<org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup
android:id="@+id/checkableGroup"
@@ -28,7 +28,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/right_to_left"
app:icon="@drawable/ic_read_reversed" />
app:icon="@drawable/ic_reader_rtl" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_webtoon"
@@ -47,4 +47,4 @@
android:text="@string/reader_mode_hint"
android:textAppearance="?attr/textAppearanceBodySmall" />
</LinearLayout>
</LinearLayout>

View File

@@ -0,0 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@drawable/sheet_toolbar_background">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navigationIcon="?actionModeCloseDrawable"
app:title="@string/options" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingBottom="@dimen/margin_normal">
<org.koitharu.kotatsu.base.ui.widgets.ListItemTextView
android:id="@+id/button_save_page"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall"
android:drawableStart="@drawable/ic_save"
android:drawablePadding="?android:listPreferredItemPaddingStart"
android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:text="@string/save_page"
android:textAppearance="?attr/textAppearanceButton" />
<org.koitharu.kotatsu.base.ui.widgets.ListItemTextView
android:id="@+id/button_screen_rotate"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall"
android:drawableStart="@drawable/ic_screen_rotation"
android:drawablePadding="?android:listPreferredItemPaddingStart"
android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:text="@string/rotate_screen"
android:textAppearance="?attr/textAppearanceButton"
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_normal"
android:text="@string/read_mode"
android:textAppearance="?textAppearanceTitleSmall" />
<org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup
android:id="@+id/checkableGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:baselineAligned="false"
android:orientation="horizontal">
<com.google.android.material.button.MaterialButton
android:id="@+id/button_standard"
style="@style/Widget.Kotatsu.ToggleButton.Vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/standard"
app:icon="@drawable/ic_reader_ltr" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_reversed"
style="@style/Widget.Kotatsu.ToggleButton.Vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_small"
android:layout_weight="1"
android:text="@string/right_to_left"
app:icon="@drawable/ic_reader_rtl" />
<com.google.android.material.button.MaterialButton
android:id="@+id/button_webtoon"
style="@style/Widget.Kotatsu.ToggleButton.Vertical"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/webtoon"
app:icon="@drawable/ic_script" />
</org.koitharu.kotatsu.base.ui.widgets.CheckableButtonGroup>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_normal"
android:layout_marginTop="@dimen/margin_small"
android:text="@string/reader_mode_hint"
android:textAppearance="?attr/textAppearanceBodySmall" />
<org.koitharu.kotatsu.base.ui.widgets.ListItemTextView
android:id="@+id/button_settings"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeightSmall"
android:layout_marginTop="@dimen/margin_normal"
android:drawableStart="@drawable/ic_settings"
android:drawablePadding="?android:listPreferredItemPaddingStart"
android:paddingStart="?android:listPreferredItemPaddingStart"
android:paddingEnd="?android:listPreferredItemPaddingEnd"
android:text="@string/settings"
android:textAppearance="?attr/textAppearanceButton" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</LinearLayout>

View File

@@ -20,7 +20,7 @@
app:showAsAction="always" />
<item
android:id="@+id/action_menu"
android:id="@+id/action_options"
android:icon="@drawable/abc_ic_menu_overflow_material"
android:title="@string/options"
app:showAsAction="always" />

View File

@@ -107,6 +107,18 @@
<item name="iconPadding">16dp</item>
</style>
<style name="Widget.Kotatsu.ToggleButton.Vertical">
<item name="android:textAlignment">center</item>
<item name="iconPadding">4dp</item>
<item name="android:singleLine">false</item>
<item name="android:lines">2</item>
<item name="android:maxLines">2</item>
<item name="iconGravity">top</item>
<item name="android:paddingTop">10dp</item>
<item name="android:paddingBottom">10dp</item>
<item name="shapeAppearance">?shapeAppearanceCornerMedium</item>
</style>
<style name="Widget.Kotatsu.RecyclerView" parent="">
<item name="android:scrollbarStyle">outsideOverlay</item>
</style>