Non-modal bottom sheet on details activity
This commit is contained in:
@@ -2,7 +2,10 @@ package org.koitharu.kotatsu.core.ui.sheet
|
|||||||
|
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.view.ViewParent
|
||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
import androidx.core.view.ancestors
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.BottomSheetCallback
|
||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
@@ -109,7 +112,16 @@ sealed class AdaptiveSheetBehavior {
|
|||||||
const val STATE_DRAGGING = SideSheetBehavior.STATE_DRAGGING
|
const val STATE_DRAGGING = SideSheetBehavior.STATE_DRAGGING
|
||||||
const val STATE_HIDDEN = SideSheetBehavior.STATE_HIDDEN
|
const val STATE_HIDDEN = SideSheetBehavior.STATE_HIDDEN
|
||||||
|
|
||||||
fun from(dialog: Dialog?): AdaptiveSheetBehavior? = when (dialog) {
|
fun from(fragment: DialogFragment): AdaptiveSheetBehavior? {
|
||||||
|
from(fragment.dialog)?.let { return it }
|
||||||
|
val rootView = fragment.view ?: return null
|
||||||
|
for (parent in rootView.ancestors) {
|
||||||
|
from(parent)?.let { return it }
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun from(dialog: Dialog?): AdaptiveSheetBehavior? = when (dialog) {
|
||||||
is BottomSheetDialog -> Bottom(dialog.behavior)
|
is BottomSheetDialog -> Bottom(dialog.behavior)
|
||||||
is SideSheetDialog -> Side(dialog.behavior)
|
is SideSheetDialog -> Side(dialog.behavior)
|
||||||
else -> null
|
else -> null
|
||||||
@@ -121,5 +133,10 @@ sealed class AdaptiveSheetBehavior {
|
|||||||
is SideSheetBehavior<*> -> Side(behavior)
|
is SideSheetBehavior<*> -> Side(behavior)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun from(parent: ViewParent): AdaptiveSheetBehavior? {
|
||||||
|
val lp = ((parent as? View)?.layoutParams as? CoordinatorLayout.LayoutParams) ?: return null
|
||||||
|
return from(lp)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import android.view.ViewGroup.LayoutParams
|
|||||||
import androidx.activity.ComponentDialog
|
import androidx.activity.ComponentDialog
|
||||||
import androidx.activity.OnBackPressedDispatcher
|
import androidx.activity.OnBackPressedDispatcher
|
||||||
import androidx.annotation.CallSuper
|
import androidx.annotation.CallSuper
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDialog
|
import androidx.appcompat.app.AppCompatDialog
|
||||||
import androidx.appcompat.app.AppCompatDialogFragment
|
import androidx.appcompat.app.AppCompatDialogFragment
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
@@ -26,6 +27,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior
|
|||||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||||
import com.google.android.material.sidesheet.SideSheetDialog
|
import com.google.android.material.sidesheet.SideSheetDialog
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.ui.BaseActivity
|
||||||
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
|
import org.koitharu.kotatsu.core.ui.util.ActionModeDelegate
|
||||||
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
import org.koitharu.kotatsu.core.util.ext.getThemeColor
|
||||||
import com.google.android.material.R as materialR
|
import com.google.android.material.R as materialR
|
||||||
@@ -44,10 +46,10 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment() {
|
|||||||
get() = requireViewBinding()
|
get() = requireViewBinding()
|
||||||
|
|
||||||
protected val behavior: AdaptiveSheetBehavior?
|
protected val behavior: AdaptiveSheetBehavior?
|
||||||
get() = AdaptiveSheetBehavior.from(dialog)
|
get() = AdaptiveSheetBehavior.from(this)
|
||||||
|
|
||||||
@JvmField
|
var actionModeDelegate: ActionModeDelegate? = null
|
||||||
val actionModeDelegate = ActionModeDelegate()
|
private set
|
||||||
|
|
||||||
val isExpanded: Boolean
|
val isExpanded: Boolean
|
||||||
get() = behavior?.state == AdaptiveSheetBehavior.STATE_EXPANDED
|
get() = behavior?.state == AdaptiveSheetBehavior.STATE_EXPANDED
|
||||||
@@ -72,11 +74,15 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment() {
|
|||||||
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
final override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
val binding = requireViewBinding()
|
val binding = requireViewBinding()
|
||||||
|
if (actionModeDelegate == null) {
|
||||||
|
actionModeDelegate = (activity as? BaseActivity<*>)?.actionModeDelegate
|
||||||
|
}
|
||||||
onViewBindingCreated(binding, savedInstanceState)
|
onViewBindingCreated(binding, savedInstanceState)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroyView() {
|
override fun onDestroyView() {
|
||||||
viewBinding = null
|
viewBinding = null
|
||||||
|
actionModeDelegate = null
|
||||||
super.onDestroyView()
|
super.onDestroyView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,13 +93,15 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment() {
|
|||||||
} else {
|
} else {
|
||||||
BottomSheetDialogImpl(context, theme)
|
BottomSheetDialogImpl(context, theme)
|
||||||
}
|
}
|
||||||
dialog.onBackPressedDispatcher.addCallback(actionModeDelegate)
|
actionModeDelegate = ActionModeDelegate().also {
|
||||||
|
dialog.onBackPressedDispatcher.addCallback(it)
|
||||||
|
}
|
||||||
return dialog
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
protected open fun dispatchSupportActionModeStarted(mode: ActionMode) {
|
protected open fun dispatchSupportActionModeStarted(mode: ActionMode) {
|
||||||
actionModeDelegate.onSupportActionModeStarted(mode)
|
actionModeDelegate?.onSupportActionModeStarted(mode)
|
||||||
val ctx = requireContext()
|
val ctx = requireContext()
|
||||||
val actionModeColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
val actionModeColor = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
ColorUtils.compositeColors(
|
ColorUtils.compositeColors(
|
||||||
@@ -119,7 +127,7 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment() {
|
|||||||
|
|
||||||
@CallSuper
|
@CallSuper
|
||||||
protected open fun dispatchSupportActionModeFinished(mode: ActionMode) {
|
protected open fun dispatchSupportActionModeFinished(mode: ActionMode) {
|
||||||
actionModeDelegate.onSupportActionModeFinished(mode)
|
actionModeDelegate?.onSupportActionModeFinished(mode)
|
||||||
dialog?.window?.statusBarColor = defaultStatusBarColor
|
dialog?.window?.statusBarColor = defaultStatusBarColor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,8 +146,8 @@ abstract class BaseAdaptiveSheet<B : ViewBinding> : AppCompatDialogFragment() {
|
|||||||
protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit
|
protected open fun onViewBindingCreated(binding: B, savedInstanceState: Bundle?) = Unit
|
||||||
|
|
||||||
fun startSupportActionMode(callback: ActionMode.Callback): ActionMode? {
|
fun startSupportActionMode(callback: ActionMode.Callback): ActionMode? {
|
||||||
val appCompatDialog = dialog as? AppCompatDialog ?: return null
|
val delegate = (dialog as? AppCompatDialog)?.delegate ?: (activity as? AppCompatActivity)?.delegate ?: return null
|
||||||
return appCompatDialog.delegate.startSupportActionMode(callback)
|
return delegate.startSupportActionMode(callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun setExpanded(isExpanded: Boolean, isLocked: Boolean) {
|
protected fun setExpanded(isExpanded: Boolean, isLocked: Boolean) {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package org.koitharu.kotatsu.core.ui.util
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_COLLAPSED
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_EXPANDED
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior.STATE_HALF_EXPANDED
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.doOnExpansionsChanged
|
||||||
|
|
||||||
|
class BottomSheetClollapseCallback(
|
||||||
|
private val behavior: BottomSheetBehavior<*>,
|
||||||
|
) : OnBackPressedCallback(behavior.state == STATE_EXPANDED) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
behavior.addBottomSheetCallback(
|
||||||
|
object : BottomSheetBehavior.BottomSheetCallback() {
|
||||||
|
|
||||||
|
override fun onStateChanged(view: View, state: Int) {
|
||||||
|
isEnabled = state == STATE_EXPANDED || state == STATE_HALF_EXPANDED
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onSlide(p0: View, p1: Float) = Unit
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
behavior.state = STATE_COLLAPSED
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,6 +31,7 @@ import coil.request.ImageRequest
|
|||||||
import coil.request.SuccessResult
|
import coil.request.SuccessResult
|
||||||
import coil.transform.CircleCropTransformation
|
import coil.transform.CircleCropTransformation
|
||||||
import coil.util.CoilUtils
|
import coil.util.CoilUtils
|
||||||
|
import com.google.android.material.bottomsheet.BottomSheetBehavior
|
||||||
import com.google.android.material.chip.Chip
|
import com.google.android.material.chip.Chip
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
@@ -52,10 +53,10 @@ import org.koitharu.kotatsu.core.ui.BaseListAdapter
|
|||||||
import org.koitharu.kotatsu.core.ui.image.ChipIconTarget
|
import org.koitharu.kotatsu.core.ui.image.ChipIconTarget
|
||||||
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
import org.koitharu.kotatsu.core.ui.image.CoverSizeResolver
|
||||||
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener
|
||||||
|
import org.koitharu.kotatsu.core.ui.util.BottomSheetClollapseCallback
|
||||||
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
import org.koitharu.kotatsu.core.ui.util.MenuInvalidator
|
||||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||||
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
import org.koitharu.kotatsu.core.ui.widgets.ChipsView
|
||||||
import org.koitharu.kotatsu.core.util.Event
|
|
||||||
import org.koitharu.kotatsu.core.util.FileSize
|
import org.koitharu.kotatsu.core.util.FileSize
|
||||||
import org.koitharu.kotatsu.core.util.ViewBadge
|
import org.koitharu.kotatsu.core.util.ViewBadge
|
||||||
import org.koitharu.kotatsu.core.util.ext.crossfade
|
import org.koitharu.kotatsu.core.util.ext.crossfade
|
||||||
@@ -68,6 +69,7 @@ import org.koitharu.kotatsu.core.util.ext.observe
|
|||||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||||
import org.koitharu.kotatsu.core.util.ext.parentView
|
import org.koitharu.kotatsu.core.util.ext.parentView
|
||||||
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
|
import org.koitharu.kotatsu.core.util.ext.scaleUpActivityOptionsOf
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.setNavigationBarTransparentCompat
|
||||||
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
import org.koitharu.kotatsu.core.util.ext.setOnContextClickListenerCompat
|
||||||
import org.koitharu.kotatsu.core.util.ext.source
|
import org.koitharu.kotatsu.core.util.ext.source
|
||||||
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
import org.koitharu.kotatsu.core.util.ext.textAndVisible
|
||||||
@@ -123,6 +125,7 @@ class DetailsActivity :
|
|||||||
private val viewModel: DetailsViewModel by viewModels()
|
private val viewModel: DetailsViewModel by viewModels()
|
||||||
|
|
||||||
private lateinit var chaptersBadge: ViewBadge
|
private lateinit var chaptersBadge: ViewBadge
|
||||||
|
private lateinit var menuProvider: DetailsMenuProvider
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -134,7 +137,7 @@ class DetailsActivity :
|
|||||||
viewBinding.buttonRead.setOnClickListener(this)
|
viewBinding.buttonRead.setOnClickListener(this)
|
||||||
viewBinding.buttonRead.setOnLongClickListener(this)
|
viewBinding.buttonRead.setOnLongClickListener(this)
|
||||||
viewBinding.buttonRead.setOnContextClickListenerCompat(this)
|
viewBinding.buttonRead.setOnContextClickListenerCompat(this)
|
||||||
viewBinding.buttonChapters?.setOnClickListener(this)
|
viewBinding.buttonDownload?.setOnClickListener(this)
|
||||||
viewBinding.infoLayout.chipBranch.setOnClickListener(this)
|
viewBinding.infoLayout.chipBranch.setOnClickListener(this)
|
||||||
viewBinding.infoLayout.chipSize.setOnClickListener(this)
|
viewBinding.infoLayout.chipSize.setOnClickListener(this)
|
||||||
viewBinding.infoLayout.chipSource.setOnClickListener(this)
|
viewBinding.infoLayout.chipSource.setOnClickListener(this)
|
||||||
@@ -152,8 +155,10 @@ class DetailsActivity :
|
|||||||
viewBinding.textViewDescription.movementMethod = LinkMovementMethodCompat.getInstance()
|
viewBinding.textViewDescription.movementMethod = LinkMovementMethodCompat.getInstance()
|
||||||
viewBinding.chipsTags.onChipClickListener = this
|
viewBinding.chipsTags.onChipClickListener = this
|
||||||
TitleScrollCoordinator(viewBinding.textViewTitle).attach(viewBinding.scrollView)
|
TitleScrollCoordinator(viewBinding.textViewTitle).attach(viewBinding.scrollView)
|
||||||
|
viewBinding.containerBottomSheet?.let { BottomSheetBehavior.from(it) }?.let { behavior ->
|
||||||
chaptersBadge = ViewBadge(viewBinding.buttonChapters ?: viewBinding.buttonRead, this)
|
onBackPressedDispatcher.addCallback(BottomSheetClollapseCallback(behavior))
|
||||||
|
}
|
||||||
|
chaptersBadge = ViewBadge(viewBinding.buttonRead, this)
|
||||||
|
|
||||||
viewModel.details.filterNotNull().observe(this, ::onMangaUpdated)
|
viewModel.details.filterNotNull().observe(this, ::onMangaUpdated)
|
||||||
viewModel.onMangaRemoved.observeEvent(this, ::onMangaRemoved)
|
viewModel.onMangaRemoved.observeEvent(this, ::onMangaRemoved)
|
||||||
@@ -187,21 +192,20 @@ class DetailsActivity :
|
|||||||
.filterNot { ChaptersPagesSheet.isShown(supportFragmentManager) }
|
.filterNot { ChaptersPagesSheet.isShown(supportFragmentManager) }
|
||||||
.observeEvent(this, DownloadStartedObserver(viewBinding.scrollView))
|
.observeEvent(this, DownloadStartedObserver(viewBinding.scrollView))
|
||||||
|
|
||||||
addMenuProvider(
|
menuProvider = DetailsMenuProvider(
|
||||||
DetailsMenuProvider(
|
activity = this,
|
||||||
activity = this,
|
viewModel = viewModel,
|
||||||
viewModel = viewModel,
|
snackbarHost = viewBinding.scrollView,
|
||||||
snackbarHost = viewBinding.scrollView,
|
appShortcutManager = shortcutManager,
|
||||||
appShortcutManager = shortcutManager,
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
|
addMenuProvider(menuProvider)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onClick(v: View) {
|
override fun onClick(v: View) {
|
||||||
when (v.id) {
|
when (v.id) {
|
||||||
R.id.button_read -> openReader(isIncognitoMode = false)
|
R.id.button_read -> openReader(isIncognitoMode = false)
|
||||||
R.id.chip_branch -> showBranchPopupMenu(v)
|
R.id.chip_branch -> showBranchPopupMenu(v)
|
||||||
R.id.button_chapters -> ChaptersPagesSheet.show(supportFragmentManager)
|
R.id.button_download -> DownloadDialogHelper(v, viewModel).show(menuProvider)
|
||||||
|
|
||||||
R.id.chip_author -> {
|
R.id.chip_author -> {
|
||||||
val manga = viewModel.manga.value ?: return
|
val manga = viewModel.manga.value ?: return
|
||||||
@@ -417,7 +421,7 @@ class DetailsActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun onLoadingStateChanged(isLoading: Boolean) {
|
private fun onLoadingStateChanged(isLoading: Boolean) {
|
||||||
val button = viewBinding.buttonChapters ?: return
|
val button = viewBinding.buttonDownload ?: return
|
||||||
if (isLoading) {
|
if (isLoading) {
|
||||||
button.setImageDrawable(
|
button.setImageDrawable(
|
||||||
CircularProgressDrawable(this).also {
|
CircularProgressDrawable(this).also {
|
||||||
@@ -427,7 +431,7 @@ class DetailsActivity :
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
button.setImageResource(R.drawable.ic_list_sheet)
|
button.setImageResource(R.drawable.ic_download)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,6 +529,9 @@ class DetailsActivity :
|
|||||||
viewBinding.scrollView.updatePadding(
|
viewBinding.scrollView.updatePadding(
|
||||||
bottom = insets.bottom,
|
bottom = insets.bottom,
|
||||||
)
|
)
|
||||||
|
viewBinding.containerBottomSheet?.let { bs ->
|
||||||
|
window.setNavigationBarTransparentCompat(this, bs.elevation, 0.9f)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onHistoryChanged(info: HistoryInfo, isLoading: Boolean) = with(viewBinding) {
|
private fun onHistoryChanged(info: HistoryInfo, isLoading: Boolean) = with(viewBinding) {
|
||||||
@@ -538,7 +545,7 @@ class DetailsActivity :
|
|||||||
else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters)
|
else -> resources.getQuantityString(R.plurals.chapters, info.totalChapters, info.totalChapters)
|
||||||
}
|
}
|
||||||
buttonRead.setProgress(info.history?.percent?.coerceIn(0f, 1f) ?: 0f, true)
|
buttonRead.setProgress(info.history?.percent?.coerceIn(0f, 1f) ?: 0f, true)
|
||||||
buttonChapters?.isEnabled = info.isValid
|
buttonDownload?.isEnabled = info.isValid
|
||||||
buttonRead.isEnabled = info.isValid
|
buttonRead.isEnabled = info.isValid
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ import org.koitharu.kotatsu.core.ui.util.ActionModeListener
|
|||||||
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
import org.koitharu.kotatsu.core.ui.util.ReversibleActionObserver
|
||||||
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
import org.koitharu.kotatsu.core.util.ext.doOnPageChanged
|
||||||
import org.koitharu.kotatsu.core.util.ext.menuView
|
import org.koitharu.kotatsu.core.util.ext.menuView
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.observe
|
||||||
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
import org.koitharu.kotatsu.core.util.ext.observeEvent
|
||||||
import org.koitharu.kotatsu.core.util.ext.recyclerView
|
|
||||||
import org.koitharu.kotatsu.core.util.ext.setTabsEnabled
|
import org.koitharu.kotatsu.core.util.ext.setTabsEnabled
|
||||||
import org.koitharu.kotatsu.core.util.ext.showDistinct
|
import org.koitharu.kotatsu.core.util.ext.showDistinct
|
||||||
import org.koitharu.kotatsu.core.util.ext.withArgs
|
import org.koitharu.kotatsu.core.util.ext.withArgs
|
||||||
@@ -46,7 +46,6 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(), Actio
|
|||||||
val args = arguments ?: Bundle.EMPTY
|
val args = arguments ?: Bundle.EMPTY
|
||||||
val defaultTab = args.getInt(ARG_TAB, settings.defaultDetailsTab)
|
val defaultTab = args.getInt(ARG_TAB, settings.defaultDetailsTab)
|
||||||
val adapter = ChaptersPagesAdapter(this, settings.isPagesTabEnabled || defaultTab == TAB_PAGES)
|
val adapter = ChaptersPagesAdapter(this, settings.isPagesTabEnabled || defaultTab == TAB_PAGES)
|
||||||
binding.pager.recyclerView?.isNestedScrollingEnabled = false
|
|
||||||
binding.pager.offscreenPageLimit = adapter.itemCount
|
binding.pager.offscreenPageLimit = adapter.itemCount
|
||||||
binding.pager.adapter = adapter
|
binding.pager.adapter = adapter
|
||||||
binding.pager.doOnPageChanged(::onPageChanged)
|
binding.pager.doOnPageChanged(::onPageChanged)
|
||||||
@@ -58,11 +57,12 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(), Actio
|
|||||||
onBackPressedDispatcher.addCallback(viewLifecycleOwner, menuProvider)
|
onBackPressedDispatcher.addCallback(viewLifecycleOwner, menuProvider)
|
||||||
binding.toolbar.addMenuProvider(menuProvider)
|
binding.toolbar.addMenuProvider(menuProvider)
|
||||||
|
|
||||||
actionModeDelegate.addListener(this, viewLifecycleOwner)
|
actionModeDelegate?.addListener(this, viewLifecycleOwner)
|
||||||
|
|
||||||
viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.pager, this))
|
viewModel.onError.observeEvent(viewLifecycleOwner, SnackbarErrorObserver(binding.pager, this))
|
||||||
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.pager, null))
|
viewModel.onActionDone.observeEvent(viewLifecycleOwner, ReversibleActionObserver(binding.pager, null))
|
||||||
viewModel.onDownloadStarted.observeEvent(viewLifecycleOwner, DownloadStartedObserver(binding.pager))
|
viewModel.onDownloadStarted.observeEvent(viewLifecycleOwner, DownloadStartedObserver(binding.pager))
|
||||||
|
viewModel.newChaptersCount.observe(viewLifecycleOwner, ::onNewChaptersChanged)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onActionModeStarted(mode: ActionMode) {
|
override fun onActionModeStarted(mode: ActionMode) {
|
||||||
@@ -97,6 +97,16 @@ class ChaptersPagesSheet : BaseAdaptiveSheet<SheetChaptersPagesBinding>(), Actio
|
|||||||
settings.lastDetailsTab = position
|
settings.lastDetailsTab = position
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun onNewChaptersChanged(counter: Int) {
|
||||||
|
val tab = viewBinding?.tabs?.getTabAt(0) ?: return
|
||||||
|
if (counter == 0) {
|
||||||
|
tab.removeBadge()
|
||||||
|
} else {
|
||||||
|
val badge = tab.orCreateBadge
|
||||||
|
badge.number = counter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|
||||||
const val TAB_CHAPTERS = 0
|
const val TAB_CHAPTERS = 0
|
||||||
|
|||||||
@@ -420,7 +420,8 @@ class MainActivity : BaseActivity<ActivityMainBinding>(), AppBarOwner, BottomNav
|
|||||||
}
|
}
|
||||||
viewBinding.container.updateLayoutParams<MarginLayoutParams> {
|
viewBinding.container.updateLayoutParams<MarginLayoutParams> {
|
||||||
bottomMargin = if (isPinned) {
|
bottomMargin = if (isPinned) {
|
||||||
bottomNavBar?.measureHeight() ?: 0
|
(bottomNavBar?.measureHeight() ?: 0)
|
||||||
|
.coerceAtLeast(resources.getDimensionPixelSize(materialR.dimen.m3_bottom_nav_min_height))
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
@@ -7,14 +7,16 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:orientation="vertical"
|
|
||||||
tools:viewBindingType="android.view.ViewGroup">
|
tools:viewBindingType="android.view.ViewGroup">
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/appbar"
|
android:id="@+id/appbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:fitsSystemWindows="true">
|
android:elevation="0dp"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
app:elevation="0dp"
|
||||||
|
app:liftOnScroll="false">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@id/toolbar"
|
android:id="@id/toolbar"
|
||||||
@@ -29,11 +31,13 @@
|
|||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:scrollIndicators="top"
|
android:scrollIndicators="top"
|
||||||
android:scrollbars="vertical">
|
android:scrollbars="vertical"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent"
|
||||||
|
android:paddingBottom="@dimen/details_bs_peek_height">
|
||||||
|
|
||||||
<com.google.android.material.imageview.ShapeableImageView
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
android:id="@+id/imageView_cover"
|
android:id="@+id/imageView_cover"
|
||||||
@@ -184,7 +188,7 @@
|
|||||||
android:paddingHorizontal="6dp"
|
android:paddingHorizontal="6dp"
|
||||||
android:paddingVertical="8dp"
|
android:paddingVertical="8dp"
|
||||||
app:baseColor="?colorSecondaryContainer"
|
app:baseColor="?colorSecondaryContainer"
|
||||||
app:layout_constraintEnd_toStartOf="@id/button_chapters"
|
app:layout_constraintEnd_toStartOf="@id/button_download"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@id/info_layout"
|
app:layout_constraintTop_toBottomOf="@id/info_layout"
|
||||||
app:progressColor="?colorPrimary"
|
app:progressColor="?colorPrimary"
|
||||||
@@ -196,19 +200,19 @@
|
|||||||
tools:title="@string/read" />
|
tools:title="@string/read" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/button_chapters"
|
android:id="@+id/button_download"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:background="@drawable/bg_circle_button"
|
android:background="@drawable/bg_circle_button"
|
||||||
android:backgroundTint="?colorSecondaryContainer"
|
android:backgroundTint="?colorSecondaryContainer"
|
||||||
android:contentDescription="@string/chapters"
|
android:contentDescription="@string/download"
|
||||||
android:scaleType="centerInside"
|
android:scaleType="centerInside"
|
||||||
app:layout_constraintBottom_toBottomOf="@id/button_read"
|
app:layout_constraintBottom_toBottomOf="@id/button_read"
|
||||||
app:layout_constraintDimensionRatio="1"
|
app:layout_constraintDimensionRatio="1"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="@id/button_read"
|
app:layout_constraintTop_toTopOf="@id/button_read"
|
||||||
app:srcCompat="@drawable/ic_list_sheet" />
|
app:srcCompat="@drawable/ic_download" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/textView_description_title"
|
android:id="@+id/textView_description_title"
|
||||||
@@ -390,4 +394,21 @@
|
|||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</LinearLayout>
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/container_bottom_sheet"
|
||||||
|
android:name="org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet"
|
||||||
|
style="@style/Widget.Material3.BottomSheet"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:elevation="6dp"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
|
android:outlineProvider="background"
|
||||||
|
app:behavior_fitToContents="false"
|
||||||
|
app:behavior_halfExpandedRatio="0.8"
|
||||||
|
app:behavior_hideable="false"
|
||||||
|
app:behavior_peekHeight="@dimen/details_bs_peek_height"
|
||||||
|
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior"
|
||||||
|
tools:layout="@layout/sheet_chapters_pages" />
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|||||||
@@ -57,6 +57,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="?android:listPreferredItemPaddingEnd"
|
android:layout_marginEnd="?android:listPreferredItemPaddingEnd"
|
||||||
android:contentDescription="@string/downloaded"
|
android:contentDescription="@string/downloaded"
|
||||||
app:srcCompat="@drawable/ic_save_ok" />
|
app:srcCompat="@drawable/ic_storage" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|||||||
@@ -35,6 +35,7 @@
|
|||||||
<dimen name="chapter_grid_width">80dp</dimen>
|
<dimen name="chapter_grid_width">80dp</dimen>
|
||||||
<dimen name="side_card_offset">8dp</dimen>
|
<dimen name="side_card_offset">8dp</dimen>
|
||||||
<dimen name="webtoon_pages_gap">24dp</dimen>
|
<dimen name="webtoon_pages_gap">24dp</dimen>
|
||||||
|
<dimen name="details_bs_peek_height">92dp</dimen>
|
||||||
|
|
||||||
<dimen name="search_suggestions_manga_height">142dp</dimen>
|
<dimen name="search_suggestions_manga_height">142dp</dimen>
|
||||||
<dimen name="search_suggestions_manga_spacing">6dp</dimen>
|
<dimen name="search_suggestions_manga_spacing">6dp</dimen>
|
||||||
|
|||||||
Reference in New Issue
Block a user