Cleaning the library controller + removing the side swipe

^Since the fast scroll exists now
Root controlllers can all now swipe up from the bottom bar to expose sheet
Added option to refresh tracking for a manga
This commit is contained in:
Jay 2020-04-06 03:10:53 -04:00
parent 83206ded5e
commit 651682df4a
24 changed files with 196 additions and 668 deletions

View File

@ -177,7 +177,7 @@ class PreferencesHelper(val context: Context) {
fun gridSize() = rxPrefs.getInteger(Keys.gridSize, 1)
fun autoHideSeeker() = rxPrefs.getBoolean("auto_hide_seeker", true)
fun alwaysShowSeeker() = rxPrefs.getBoolean("always_show_seeker", false)
fun uniformGrid() = rxPrefs.getBoolean(Keys.uniformGrid, true)

View File

@ -2,12 +2,8 @@ package eu.kanade.tachiyomi.ui.base
import android.content.Context
import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
import androidx.appcompat.widget.PopupMenu
import com.google.android.material.appbar.MaterialToolbar
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.main_activity.view.*
class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@ -44,20 +40,4 @@ class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: Attribut
super.setTitle(null)
}
}
fun showSpinner(): PopupMenu {
val popupMenu = PopupMenu(context, title_layout, Gravity.CENTER)
dropdown.visible()
title_layout.setOnTouchListener(popupMenu.dragToOpenListener)
title_layout.setOnClickListener {
popupMenu.show()
}
return popupMenu
}
fun removeSpinner() {
dropdown.gone()
title_layout.setOnTouchListener(null)
title_layout.setOnClickListener(null)
}
}

View File

@ -67,8 +67,6 @@ abstract class BaseController(bundle: Bundle? = null) : RestoreViewOnCreateContr
val onRoot: Boolean
get() = router.backstack.lastOrNull()?.controller() == this
open fun handleRootBack(): Boolean = false
open fun getTitle(): String? {
return null
}

View File

@ -28,6 +28,7 @@ import eu.kanade.tachiyomi.ui.catalogue.browse.BrowseCatalogueController
import eu.kanade.tachiyomi.ui.catalogue.global_search.CatalogueSearchController
import eu.kanade.tachiyomi.ui.catalogue.latest.LatestUpdatesController
import eu.kanade.tachiyomi.ui.extension.SettingsExtensionsController
import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
import eu.kanade.tachiyomi.ui.setting.SettingsSourcesController
@ -55,7 +56,7 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
FlexibleAdapter.OnItemClickListener,
CatalogueAdapter.OnBrowseClickListener,
RootSearchInterface,
BottomSheetController,
CatalogueAdapter.OnLatestClickListener {
/**
@ -180,11 +181,11 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
}
}
fun showExtensions() {
override fun showSheet() {
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
fun toggleExtensions() {
override fun toggleSheet() {
if (ext_bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) {
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
} else {
@ -192,7 +193,7 @@ class CatalogueController : NucleusController<CataloguePresenter>(),
}
}
override fun handleRootBack(): Boolean {
override fun handleSheetBack(): Boolean {
if (ext_bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED) {
ext_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
return true

View File

@ -72,8 +72,7 @@ class DownloadBottomSheet @JvmOverloads constructor(
}
}
update()
setBottomSheet()
setInformationView()
if (sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED && sheetBehavior?.isHideable == true) sheetBehavior?.state =
BottomSheetBehavior.STATE_HIDDEN
}

View File

@ -86,8 +86,8 @@ class DisplayBottomSheet(private val controller: LibraryController) : BottomShee
uniform_grid.bindToPreference(preferences.uniformGrid()) {
controller.reattachAdapter()
}
autohide_seeker.bindToPreference(preferences.autoHideSeeker()) {
controller.updateAutoHideScrollbar(autohide_seeker.isChecked)
autohide_seeker.bindToPreference(preferences.alwaysShowSeeker()) {
controller.updateShowScrollbar(autohide_seeker.isChecked)
}
grid_size_toggle_group.bindToPreference(preferences.gridSize()) {
controller.reattachAdapter()

View File

@ -7,7 +7,6 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.lang.removeArticles
import uy.kohesive.injekt.injectLazy
import java.text.SimpleDateFormat
@ -158,7 +157,9 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
val preferences: PreferencesHelper by injectLazy()
val db: DatabaseHelper by injectLazy()
return when (val iFlexible: IFlexible<*>? = getItem(position)) {
is LibraryHeaderItem -> iFlexible.category.name
is LibraryHeaderItem ->
if (!preferences.hideCategories().getOrDefault()) iFlexible.category.name
else recyclerView.context.getString(R.string.top)
is LibraryItem -> {
when (preferences.librarySortingMode().getOrDefault()) {
LibrarySort.DRAG_AND_DROP -> {
@ -170,8 +171,7 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
} else {
val category = db.getCategoriesForManga(iFlexible.manga)
.executeAsBlocking().firstOrNull()?.name
category?.chop(10)
?: recyclerView.context.getString(R.string.default_category)
category ?: recyclerView.context.getString(R.string.default_columns)
}
}
LibrarySort.LAST_READ -> {
@ -265,6 +265,5 @@ class LibraryCategoryAdapter(val libraryListener: LibraryListener) :
fun sortCategory(catId: Int, sortBy: Int)
fun selectAll(position: Int)
fun allSelected(position: Int): Boolean
fun recyclerIsScrolling(): Boolean
}
}

View File

@ -1,19 +1,14 @@
package eu.kanade.tachiyomi.ui.library
import android.animation.Animator
import android.animation.AnimatorSet
import android.animation.ValueAnimator
import android.app.Activity
import android.content.Context
import android.content.res.ColorStateList
import android.graphics.Rect
import android.os.Bundle
import android.util.TypedValue
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import android.view.ViewPropertyAnimator
@ -53,10 +48,9 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.library.filter.FilterBottomSheet
import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.OnTouchEventInterface
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
import eu.kanade.tachiyomi.ui.main.SwipeGestureInterface
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
import eu.kanade.tachiyomi.ui.migration.manga.process.MigrationListController
@ -81,11 +75,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Locale
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.sign
class LibraryController(
bundle: Bundle? = null,
@ -95,7 +85,7 @@ class LibraryController(
ChangeMangaCategoriesDialog.Listener,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.OnItemMoveListener, LibraryCategoryAdapter.LibraryListener,
OnTouchEventInterface, SwipeGestureInterface,
BottomSheetController,
RootSearchInterface, LibraryServiceListener {
init {
@ -133,14 +123,9 @@ class LibraryController(
private var lastClickPosition = -1
private var updateScroll = true
private var lastItemPosition: Int? = null
private var lastItem: IFlexible<*>? = null
private var switchingCategories = false
var scrollDistance = 0f
lateinit var presenter: LibraryPresenter
private set
@ -148,23 +133,12 @@ class LibraryController(
var snack: Snackbar? = null
// Horizontal scroll values
private var startPosX: Float? = null
private var startPosY: Float? = null
private var moved = false
private var lockedRecycler = false
private var lockedY = false
private var nextCategory: Int? = null
private var ogCategory: Int? = null
private var prevCategory: Int? = null
private val swipeDistance = 500f
private var flinging = false
private var isDragging = false
private var scrollDistance = 0f
private val scrollDistanceTilHidden = 1000.dpToPx
private var textAnim: ViewPropertyAnimator? = null
private var scrollAnim: ViewPropertyAnimator? = null
private var autoHideScroller: Boolean = preferences.autoHideSeeker().getOrDefault()
private var alwaysShowScroller: Boolean = preferences.alwaysShowSeeker().getOrDefault()
override fun getTitle(): String? {
return if (view != null && presenter.categories.size > 1) presenter.categories.find {
@ -193,7 +167,7 @@ class LibraryController(
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState)
if (!autoHideScroller) return
if (alwaysShowScroller) return
when (newState) {
RecyclerView.SCROLL_STATE_DRAGGING -> {
scrollAnim?.cancel()
@ -212,24 +186,23 @@ class LibraryController(
}
private fun hideScroller() {
if (!autoHideScroller) return
scrollAnim = fast_scroller.animate()
.setStartDelay(1000)
.setDuration(250)
.translationX(22f.dpToPx)
if (alwaysShowScroller) return
scrollAnim =
fast_scroller.animate().setStartDelay(1000).setDuration(250).translationX(22f.dpToPx)
scrollAnim?.start()
}
private fun setFastScrollBackground() {
val context = activity ?: return
fast_scroller.background = if (autoHideScroller) ContextCompat.getDrawable(
fast_scroller.background = if (!alwaysShowScroller) ContextCompat.getDrawable(
context, R.drawable.fast_scroll_background
) else null
fast_scroller.textColor = ColorStateList.valueOf(
context.getResourceColor(
if (autoHideScroller) android.R.attr.textColorPrimaryInverse else android.R.attr.textColorPrimary
if (!alwaysShowScroller) android.R.attr.textColorPrimaryInverse else android.R.attr.textColorPrimary
)
)
fast_scroller.iconColor = fast_scroller.textColor
}
override fun onViewCreated(view: View) {
@ -252,15 +225,15 @@ class LibraryController(
})
recycler.setHasFixedSize(true)
recycler.adapter = adapter
fast_scroller.setupWithRecyclerView(
recycler, { position ->
val letter = adapter.getSectionText(position)
if (!singleCategory && !adapter.isHeader(adapter.getItem(position))) null
else if (letter != null) FastScrollItemIndicator.Text(letter)
else FastScrollItemIndicator.Icon(R.drawable.star)
})
fast_scroller.setupWithRecyclerView(recycler, { position ->
val letter = adapter.getSectionText(position)
if (!singleCategory && !adapter.isHeader(adapter.getItem(position))) null
else if (letter != null) FastScrollItemIndicator.Text(letter)
else FastScrollItemIndicator.Icon(R.drawable.star)
})
fast_scroller.useDefaultScroller = false
fast_scroller.itemIndicatorSelectedCallbacks += object : FastScrollerView.ItemIndicatorSelectedCallback {
fast_scroller.itemIndicatorSelectedCallbacks += object :
FastScrollerView.ItemIndicatorSelectedCallback {
override fun onItemIndicatorSelected(
indicator: FastScrollItemIndicator,
indicatorCenterY: Int,
@ -271,17 +244,21 @@ class LibraryController(
textAnim?.cancel()
textAnim = text_view_m.animate().alpha(0f).setDuration(250L).setStartDelay(1000)
textAnim?.start()
this@LibraryController.view?.post {
textAnim?.start()
}
text_view_m.translationY = indicatorCenterY.toFloat() - text_view_m.height / 2
text_view_m.alpha = 1f
text_view_m.text = adapter.onCreateBubbleText(itemPosition)
val appbar = activity?.appbar
appbar?.y = 0f
recycler.suppressLayout(true)
(recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(
itemPosition,
if (singleCategory) 0 else (if (itemPosition == 0) 0 else (-40).dpToPx)
)
recycler.suppressLayout(false)
}
}
recycler.addOnScrollListener(scrollListener)
@ -295,7 +272,6 @@ class LibraryController(
}
}
swipe_refresh.setDistanceToTriggerSync(150.dpToPx)
swipe_refresh.setOnRefreshListener {
swipe_refresh.isRefreshing = false
if (!LibraryUpdateService.isRunning()) {
@ -316,9 +292,7 @@ class LibraryController(
0 -> updateLibrary(presenter.allCategories.first())
else -> updateLibrary()
}
})
.positiveButton(R.string.action_update)
.show()
}).positiveButton(R.string.action_update).show()
}
else -> {
when (preferences.updateOnRefresh().getOrDefault()) {
@ -360,110 +334,6 @@ class LibraryController(
}
}
override fun onTouchEvent(event: MotionEvent?) {
if (event == null) {
resetScrollingValues()
resetRecyclerY()
return
}
if (flinging || presenter.categories.size <= 1) return
if (isDragging) {
resetScrollingValues()
resetRecyclerY(false)
return
}
val sheetRect = Rect()
val recyclerRect = Rect()
val appBarRect = Rect()
bottom_sheet.getGlobalVisibleRect(sheetRect)
view?.getGlobalVisibleRect(recyclerRect)
activity?.appbar?.getGlobalVisibleRect(appBarRect)
if (startPosX == null) {
startPosX = event.rawX
startPosY = event.rawY
val position =
(recycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
val order = activeCategory
ogCategory = order
var newOffsetN = order + 1
while (adapter.indexOf(newOffsetN) == -1 && presenter.categories.any { it.order == newOffsetN }) {
newOffsetN += 1
}
if (adapter.indexOf(newOffsetN) != -1) nextCategory = newOffsetN
if (position == 0) prevCategory = null
else {
var newOffsetP = order - 1
while (adapter.indexOf(newOffsetP) == -1 && presenter.categories.any { it.order == newOffsetP }) {
newOffsetP -= 1
}
if (adapter.indexOf(newOffsetP) != -1) prevCategory = newOffsetP
}
return
}
if (event.actionMasked == MotionEvent.ACTION_UP) {
recycler_layout.post {
if (!flinging) {
resetScrollingValues()
resetRecyclerY(true)
}
}
return
}
if (startPosX != null && startPosY != null && (sheetRect.contains(
startPosX!!.toInt(),
startPosY!!.toInt()
) || !recyclerRect.contains(
startPosX!!.toInt(),
startPosY!!.toInt()
) || appBarRect.contains(startPosX!!.toInt(), startPosY!!.toInt()))
) {
return
}
if (event.actionMasked != MotionEvent.ACTION_UP && startPosX != null) {
val distance = abs(event.rawX - startPosX!!)
val sign = sign(event.rawX - startPosX!!)
if (lockedY) return
if (distance > 60 && abs(event.rawY - startPosY!!) <= 30 && !lockedRecycler) {
swipe_refresh.isEnabled = false
lockedRecycler = true
switchingCategories = true
recycler.suppressLayout(true)
} else if (!lockedRecycler && abs(event.rawY - startPosY!!) > 30) {
lockedY = true
resetRecyclerY()
return
}
if (abs(event.rawY - startPosY!!) <= 30 || recycler.isLayoutSuppressed || lockedRecycler) {
if ((prevCategory == null && sign > 0) || (nextCategory == null && sign < 0)) {
recycler_layout.x = sign * distance.pow(0.6f)
recycler_layout.alpha = 1f
} else if (distance <= swipeDistance * 1.1f) {
recycler_layout.x = sign * (distance / (swipeDistance / 3f)).pow(3.5f)
recycler_layout.alpha =
(1f - (distance - (swipeDistance * 0.1f)) / swipeDistance)
if (moved) {
scrollToHeader(ogCategory ?: -1)
moved = false
}
} else {
if (!moved) {
scrollToHeader((if (sign <= 0) nextCategory else prevCategory) ?: -1)
moved = true
}
recycler_layout.x = -sign * (max(0f, (swipeDistance * 2 - distance)) /
(swipeDistance / 3f)).pow(3.5f)
recycler_layout.alpha = ((distance - swipeDistance * 1.1f) / swipeDistance)
recycler_layout.alpha = min(1f, recycler_layout.alpha)
}
}
}
}
private fun getCategoryOrder(): Int? {
val position =
(recycler.layoutManager as LinearLayoutManager).findFirstCompletelyVisibleItemPosition()
@ -484,57 +354,16 @@ class LibraryController(
return order
}
private fun resetScrollingValues() {
swipe_refresh.isEnabled = !isDragging
startPosX = null
startPosY = null
nextCategory = null
prevCategory = null
ogCategory = null
lockedY = false
}
fun updateAutoHideScrollbar(autoHide: Boolean) {
autoHideScroller = autoHide
fun updateShowScrollbar(show: Boolean) {
alwaysShowScroller = show
setFastScrollBackground()
if (libraryLayout == 0) reattachAdapter()
scrollAnim?.cancel()
if (autoHide) hideScroller()
else fast_scroller.translationX = 0f
if (show) fast_scroller.translationX = 0f
else hideScroller()
setRecyclerLayout()
}
private fun resetRecyclerY(animated: Boolean = false, time: Long = 100) {
swipe_refresh.isEnabled = !isDragging
moved = false
lockedRecycler = false
if (animated) {
val set = AnimatorSet()
val translationXAnimator = ValueAnimator.ofFloat(recycler_layout.x, 0f)
translationXAnimator.duration = time
translationXAnimator.addUpdateListener { animation ->
recycler_layout.x = animation.animatedValue as Float
}
val translationAlphaAnimator = ValueAnimator.ofFloat(recycler_layout.alpha, 1f)
translationAlphaAnimator.duration = time
translationAlphaAnimator.addUpdateListener { animation ->
recycler_layout.alpha = animation.animatedValue as Float
}
set.playTogether(translationXAnimator, translationAlphaAnimator)
set.start()
launchUI {
delay(time)
if (!lockedRecycler) switchingCategories = false
}
} else {
recycler_layout.x = 0f
recycler_layout.alpha = 1f
switchingCategories = false
}
recycler.suppressLayout(false)
}
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
return inflater.inflate(R.layout.library_list_controller, container, false)
}
@ -550,12 +379,15 @@ class LibraryController(
private fun setRecyclerLayout() {
if (libraryLayout == 0) {
recycler.spanCount = 1
recycler.updatePaddingRelative(start = 0, end = if (!autoHideScroller) 10.dpToPx else 0)
recycler.updatePaddingRelative(
start = 0,
end = 0
)
} else {
recycler.columnWidth = (90 + (preferences.gridSize().getOrDefault() * 30)).dpToPx
recycler.updatePaddingRelative(
start = (if (!autoHideScroller) 2 else 5).dpToPx,
end = (if (!autoHideScroller) 12 else 5).dpToPx
start = (if (alwaysShowScroller) 2 else 5).dpToPx,
end = (if (alwaysShowScroller) 12 else 5).dpToPx
)
}
}
@ -563,11 +395,6 @@ class LibraryController(
override fun onChangeStarted(handler: ControllerChangeHandler, type: ControllerChangeType) {
super.onChangeStarted(handler, type)
if (type.isEnter) {
/*if (presenter.categories.size > 1) {
activity?.toolbar?.showSpinner()
} else {
activity?.toolbar?.removeSpinner()
}*/
presenter.getLibrary()
DownloadService.callListeners()
LibraryUpdateService.setListener(this)
@ -581,8 +408,6 @@ class LibraryController(
if (observeLater && ::presenter.isInitialized) {
presenter.getLibrary()
}
resetScrollingValues()
resetRecyclerY()
}
override fun onActivityPaused(activity: Activity) {
@ -617,62 +442,32 @@ class LibraryController(
adapter.setItems(mangaMap)
singleCategory = presenter.categories.size <= 1
fast_scroller.translationX = 0f
hideScroller()
setTitle()
updateScroll = false
if (!freshStart) {
justStarted = false
if (recycler_layout.alpha == 0f) recycler_layout.animate().alpha(1f).setDuration(500)
.start()
} else if (justStarted) {
if (freshStart) scrollToHeader(activeCategory)
} else {
updateScroll = true
} else if (justStarted && freshStart) {
scrollToHeader(activeCategory)
fast_scroller.translationX = 0f
hideScroller()
}
adapter.isLongPressDragEnabled = canDrag()
/*val popupMenu = if (presenter.categories.size > 1 && isCurrentController) {
activity?.toolbar?.showSpinner()
} else {
activity?.toolbar?.removeSpinner()
null
}*/
/*presenter.categories.forEach { category ->
popupMenu?.menu?.add(0, category.order, max(0, category.order), category.name)
}
popupMenu?.setOnMenuItemClickListener { item ->
scrollToHeader(item.itemId)
true
}*/
}
private fun scrollToHeader(pos: Int) {
val headerPosition = adapter.indexOf(pos)
switchingCategories = true
if (headerPosition > -1) {
val appbar = activity?.appbar
recycler.suppressLayout(true)
val appbarOffset = if (appbar?.y ?: 0f > -20) 0 else (appbar?.y?.plus(
view?.rootWindowInsets?.systemWindowInsetTop ?: 0
) ?: 0f).roundToInt() + 30.dpToPx
view?.rootWindowInsets?.systemWindowInsetTop ?: 0
) ?: 0f).roundToInt() + 30.dpToPx
(recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(
headerPosition, (if (headerPosition == 0) 0 else (-40).dpToPx) + appbarOffset
)
/*val headerItem = adapter.getItem(headerPosition) as? LibraryHeaderItem
if (headerItem != null) {
setTitle()
}*/
recycler.suppressLayout(false)
}
launchUI {
delay(100)
switchingCategories = false
}
}
private fun onRefresh() {
@ -763,13 +558,16 @@ class LibraryController(
}
override fun startReading(position: Int) {
if (recyclerIsScrolling()) return
if (adapter.mode == SelectableAdapter.Mode.MULTI) {
toggleSelection(position)
return
}
val manga = (adapter.getItem(position) as? LibraryItem)?.manga ?: return
startReading(manga)
val activity = activity ?: return
val chapter = presenter.getFirstUnread(manga) ?: return
val intent = ReaderActivity.newIntent(activity, manga, chapter)
destroyActionModeIfNeeded()
startActivity(intent)
}
private fun toggleSelection(position: Int) {
@ -792,7 +590,6 @@ class LibraryController(
* @return true if the item should be selected, false otherwise.
*/
override fun onItemClick(view: View?, position: Int): Boolean {
if (recyclerIsScrolling()) return false
val item = adapter.getItem(position) as? LibraryItem ?: return false
return if (adapter.mode == SelectableAdapter.Mode.MULTI) {
lastClickPosition = position
@ -804,9 +601,11 @@ class LibraryController(
}
}
private fun openManga(manga: Manga) = router.pushController(MangaDetailsController(
manga
).withFadeTransaction())
private fun openManga(manga: Manga) = router.pushController(
MangaDetailsController(
manga
).withFadeTransaction()
)
/**
* Called when a manga is long clicked.
@ -814,7 +613,6 @@ class LibraryController(
* @param position the position of the element clicked.
*/
override fun onItemLongClick(position: Int) {
if (recyclerIsScrolling()) return
if (adapter.getItem(position) is LibraryHeaderItem) return
createActionModeIfNeeded()
when {
@ -834,7 +632,6 @@ class LibraryController(
val position = viewHolder?.adapterPosition ?: return
swipe_refresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_DRAG
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
isDragging = true
activity?.appbar?.y = 0f
if (lastItemPosition != null && position != lastItemPosition && lastItem == adapter.getItem(
position
@ -875,27 +672,17 @@ class LibraryController(
else if (lastItemPosition == null) lastItemPosition = fromPosition
}
fun toggleFilters() {
if (bottom_sheet.sheetBehavior?.isHideable == true && bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_HIDDEN
else if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_COLLAPSED && bottom_sheet.sheetBehavior?.skipCollapsed == false) bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_COLLAPSED
else bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
override fun shouldMoveItem(fromPosition: Int, toPosition: Int): Boolean {
if (adapter.isSelected(fromPosition)) toggleSelection(fromPosition)
val item = adapter.getItem(fromPosition) as? LibraryItem ?: return false
val newHeader = adapter.getSectionHeader(toPosition) as? LibraryHeaderItem
if (toPosition <= 1) return false
return (adapter.getItem(toPosition) !is LibraryHeaderItem) && (newHeader?.category?.id == item.manga.category || !presenter.mangaIsInCategory(
item.manga,
newHeader?.category?.id
item.manga, newHeader?.category?.id
))
}
override fun onItemReleased(position: Int) {
isDragging = false
if (adapter.selectedItemCount > 0) {
lastItemPosition = null
return
@ -1009,66 +796,25 @@ class LibraryController(
return items.all { adapter.isSelected(it) }
}
override fun onSwipeBottom(x: Float, y: Float) {}
override fun onSwipeTop(x: Float, y: Float) {
val sheetRect = Rect()
activity!!.bottom_nav.getGlobalVisibleRect(sheetRect)
if (sheetRect.contains(x.toInt(), y.toInt())) {
if (bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED) toggleFilters()
override fun showSheet() {
if (bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_HIDDEN) bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_COLLAPSED
else bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
override fun toggleSheet() {
when {
bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_HIDDEN -> bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_COLLAPSED
bottom_sheet.sheetBehavior?.state != BottomSheetBehavior.STATE_EXPANDED -> bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_EXPANDED
bottom_sheet.sheetBehavior?.isHideable == true -> bottom_sheet.sheetBehavior?.state =
BottomSheetBehavior.STATE_HIDDEN
else -> bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_COLLAPSED
}
}
override fun onSwipeLeft(x: Float, xPos: Float) = goToNextCategory(x, xPos)
override fun onSwipeRight(x: Float, xPos: Float) = goToNextCategory(x, xPos)
private fun goToNextCategory(x: Float, xPos: Float) {
if (lockedRecycler && abs(x) > 1000f) {
val sign = sign(x).roundToInt()
if ((sign < 0 && nextCategory == null) || (sign > 0) && prevCategory == null) return
val distance = recycler_layout.alpha
val speed = max(5000f / abs(x), 0.75f)
if (sign(recycler_layout.x) == sign(x)) {
flinging = true
val duration = (distance * 100 * speed).toLong()
val set = AnimatorSet()
val translationXAnimator = ValueAnimator.ofFloat(abs(xPos - startPosX!!),
swipeDistance)
translationXAnimator.duration = duration
translationXAnimator.addUpdateListener { animation ->
recycler_layout.x = sign *
(animation.animatedValue as Float / (swipeDistance / 3f)).pow(3.5f)
}
val translationAlphaAnimator = ValueAnimator.ofFloat(recycler_layout.alpha, 0f)
translationAlphaAnimator.duration = duration
translationAlphaAnimator.addUpdateListener { animation ->
recycler_layout.alpha = animation.animatedValue as Float
}
set.playTogether(translationXAnimator, translationAlphaAnimator)
set.start()
set.addListener(object : Animator.AnimatorListener {
override fun onAnimationEnd(animation: Animator?) {
recycler_layout.x = -sign * (swipeDistance / (swipeDistance / 3f)).pow(3.5f)
recycler_layout.alpha = 0f
recycler_layout.post {
scrollToHeader((if (sign <= 0) nextCategory else prevCategory) ?: -1)
recycler_layout.post {
resetScrollingValues()
resetRecyclerY(true, (100 * speed).toLong())
flinging = false
}
}
}
override fun onAnimationCancel(animation: Animator?) {}
override fun onAnimationRepeat(animation: Animator?) {}
override fun onAnimationStart(animation: Animator?) {}
})
}
}
}
override fun handleRootBack(): Boolean {
override fun handleSheetBack(): Boolean {
val sheetBehavior = BottomSheetBehavior.from(bottom_sheet)
if (sheetBehavior.state != BottomSheetBehavior.STATE_COLLAPSED && sheetBehavior.state != BottomSheetBehavior.STATE_HIDDEN) {
sheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
@ -1131,7 +877,7 @@ class LibraryController(
/**
* Invalidates the action mode, forcing it to refresh its content.
*/
fun invalidateActionMode() {
private fun invalidateActionMode() {
actionMode?.invalidate()
}
@ -1214,15 +960,6 @@ class LibraryController(
destroyActionModeIfNeeded()
}
// / Method for the category view
private fun startReading(manga: Manga) {
val activity = activity ?: return
val chapter = presenter.getFirstUnread(manga) ?: return
val intent = ReaderActivity.newIntent(activity, manga, chapter)
destroyActionModeIfNeeded()
startActivity(intent)
}
/**
* Move the selected manga to a list of categories.
*/
@ -1241,6 +978,4 @@ class LibraryController(
router
)
}
override fun recyclerIsScrolling() = switchingCategories || lockedRecycler || lockedY
}

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.library
import android.graphics.drawable.Drawable
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.view.menu.MenuBuilder
@ -9,6 +10,7 @@ import androidx.appcompat.widget.PopupMenu
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.f2prateek.rx.preferences.Preference
import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.SelectableAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem
@ -17,6 +19,7 @@ import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.system.getResourceColor
import eu.kanade.tachiyomi.util.view.gone
@ -24,7 +27,11 @@ import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.library_category_header_item.view.*
class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int) :
class LibraryHeaderItem(
private val categoryF: (Int) -> Category,
private val catId: Int,
private val showFastScroll: Preference<Boolean>
) :
AbstractHeaderItem<LibraryHeaderItem.Holder>() {
override fun getLayoutRes(): Int {
@ -35,7 +42,7 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
view: View,
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>
): Holder {
return Holder(view, adapter as LibraryCategoryAdapter)
return Holder(view, adapter as LibraryCategoryAdapter, showFastScroll.getOrDefault())
}
override fun bindViewHolder(
@ -70,7 +77,7 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
return -(category.id!!)
}
class Holder(val view: View, private val adapter: LibraryCategoryAdapter) :
class Holder(val view: View, private val adapter: LibraryCategoryAdapter, padEnd: Boolean) :
FlexibleViewHolder(view, adapter, true) {
private val sectionText: TextView = view.findViewById(R.id.category_title)
@ -79,6 +86,9 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
private val checkboxImage: ImageView = view.findViewById(R.id.checkbox)
init {
sortText.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = (if (padEnd && adapter.recyclerView.paddingEnd == 0) 12 else 2).dpToPx
}
updateButton.setOnClickListener { addCategoryToUpdate() }
sortText.setOnClickListener { it.post { showCatSortOptions() } }
checkboxImage.setOnClickListener { selectAll() }
@ -140,7 +150,6 @@ class LibraryHeaderItem(private val categoryF: (Int) -> Category, val catId: Int
}
}
private fun showCatSortOptions() {
if (adapter.libraryListener.recyclerIsScrolling()) return
val category =
(adapter.getItem(adapterPosition) as? LibraryHeaderItem)?.category ?: return
// Create a PopupMenu, giving it the clicked view for an anchor

View File

@ -28,6 +28,7 @@ class LibraryItem(
val manga: LibraryManga,
private val libraryLayout: Preference<Int>,
private val fixedSize: Preference<Boolean>,
private val showFastScroll: Preference<Boolean>,
header: LibraryHeaderItem?
) :
AbstractSectionableItem<LibraryHolder, LibraryHeaderItem?>(header), IFilterable<String> {
@ -49,7 +50,7 @@ class LibraryItem(
val libraryLayout = libraryLayout.getOrDefault()
val isFixedSize = fixedSize.getOrDefault()
if (libraryLayout == 0 || manga.isBlank()) {
LibraryListHolder(view, adapter as LibraryCategoryAdapter)
LibraryListHolder(view, adapter as LibraryCategoryAdapter, showFastScroll.getOrDefault())
} else {
view.apply {
val coverHeight = (parent.itemWidth / 3f * 4f).toInt()
@ -94,7 +95,7 @@ class LibraryItem(
)
}
} else {
LibraryListHolder(view, adapter as LibraryCategoryAdapter)
LibraryListHolder(view, adapter as LibraryCategoryAdapter, showFastScroll.getOrDefault())
}
}

View File

@ -1,13 +1,16 @@
package eu.kanade.tachiyomi.ui.library
import android.view.View
import android.view.ViewGroup
import com.bumptech.glide.Glide
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.signature.ObjectKey
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.glide.GlideApp
import eu.kanade.tachiyomi.util.system.dpToPx
import eu.kanade.tachiyomi.util.view.gone
import eu.kanade.tachiyomi.util.view.updateLayoutParams
import eu.kanade.tachiyomi.util.view.visible
import kotlinx.android.synthetic.main.catalogue_list_item.*
import kotlinx.android.synthetic.main.catalogue_list_item.view.*
@ -25,9 +28,16 @@ import kotlinx.android.synthetic.main.unread_download_badge.*
class LibraryListHolder(
private val view: View,
adapter: LibraryCategoryAdapter
adapter: LibraryCategoryAdapter,
padEnd: Boolean
) : LibraryHolder(view, adapter) {
init {
badge_view?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
marginEnd = (if (padEnd) 22 else 12).dpToPx
}
}
/**
* Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this
* holder with the given manga.

View File

@ -468,56 +468,43 @@ class LibraryPresenter(
val showCategories = !preferences.hideCategories().getOrDefault()
val unreadBadgeType = preferences.unreadBadgeType().getOrDefault()
var libraryManga = db.getLibraryMangas().executeAsBlocking()
val singleList = true
val seekPref = preferences.alwaysShowSeeker()
if (!showCategories)
libraryManga = libraryManga.distinctBy { it.id }
/*val libraryMap = libraryManga.map { manga ->
LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.groupBy {
if (showCategories) it.manga.category else 0
}*/
val categoryAll = Category.createAll(context,
preferences.librarySortingMode().getOrDefault(),
preferences.librarySortingAscending().getOrDefault())
val catItemAll = LibraryHeaderItem({ categoryAll }, -1)
val catItemAll = LibraryHeaderItem({ categoryAll }, -1, seekPref)
val libraryMap =
if (!singleList) {
libraryManga.map { manga ->
LibraryItem(manga, libraryLayout, preferences.uniformGrid(), null).apply { unreadType =
unreadBadgeType }
}.groupBy {
if (showCategories) it.manga.category else -1
libraryManga.groupBy { manga ->
if (showCategories) manga.category else -1
// LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.map { entry ->
val categoryItem =
if (!showCategories) catItemAll else
(LibraryHeaderItem({ getCategory(it) }, entry.key, seekPref))
entry.value.map {
LibraryItem(
it, libraryLayout, preferences.uniformGrid(), seekPref, categoryItem
).apply { unreadType = unreadBadgeType }
}
} else {
libraryManga.groupBy { manga ->
if (showCategories) manga.category else -1
// LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.map { entry ->
val categoryItem =
if (!showCategories) catItemAll else
(LibraryHeaderItem({ getCategory(it) }, entry.key))
entry.value.map {
LibraryItem(
it, libraryLayout, preferences.uniformGrid(), categoryItem
).apply { unreadType = unreadBadgeType }
}
}.map {
val cat = if (showCategories) it.firstOrNull()?.manga?.category ?: 0 else -1
cat to it
// LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.toMap()
}.toMutableMap()
}.map {
val cat = if (showCategories) it.firstOrNull()?.manga?.category ?: 0 else -1
cat to it
// LibraryItem(manga, libraryLayout).apply { unreadType = unreadBadgeType }
}.toMap().toMutableMap()
if (showCategories) {
categories.forEach { category ->
if (category.id ?: 0 <= 0 && !libraryMap.containsKey(category.id)) {
val headerItem =
LibraryHeaderItem({ getCategory(category.id!!) }, category.id!!)
LibraryHeaderItem({ getCategory(category.id!!) }, category.id!!, seekPref)
libraryMap[category.id!!] = listOf(
LibraryItem(
LibraryManga.createBlank(category.id!!),
libraryLayout,
preferences.uniformGrid(),
preferences.alwaysShowSeeker(),
headerItem
)
)

View File

@ -81,7 +81,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
private set
private var searchDrawable: Drawable? = null
private var dismissDrawable: Drawable? = null
private var currentGestureDelegate: SwipeGestureInterface? = null
private lateinit var gestureDetector: GestureDetectorCompat
private var snackBar: Snackbar? = null
@ -156,23 +155,9 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
}, id)
} else if (currentRoot.tag()?.toIntOrNull() == id) {
if (router.backstackSize == 1) {
when (id) {
R.id.nav_recents -> {
val controller =
router.getControllerWithTag(id.toString()) as? RecentsController
controller?.toggleDownloads()
}
R.id.nav_library -> {
val controller =
router.getControllerWithTag(id.toString()) as? LibraryController
controller?.toggleFilters()
}
R.id.nav_catalogues -> {
val controller =
router.getControllerWithTag(id.toString()) as? CatalogueController
controller?.toggleExtensions()
}
}
val controller =
router.getControllerWithTag(id.toString()) as? BottomSheetController
controller?.toggleSheet()
}
}
true
@ -389,7 +374,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
bottom_nav.post {
val controller =
router.backstack.firstOrNull()?.controller() as? CatalogueController
controller?.showExtensions()
controller?.showSheet()
}
}
SHORTCUT_MANGA -> {
@ -398,12 +383,12 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
router.pushController(MangaDetailsController(extras).withFadeTransaction())
}
SHORTCUT_DOWNLOADS -> {
bottom_nav.selectedItemId = R.id.nav_catalogues
bottom_nav.selectedItemId = R.id.nav_recents
router.popToRoot()
bottom_nav.post {
val controller =
router.backstack.firstOrNull()?.controller() as? RecentsController
controller?.showDownloads()
controller?.showSheet()
}
}
Intent.ACTION_SEARCH, "com.google.android.gms.actions.SEARCH_ACTION" -> {
@ -446,21 +431,13 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
}
override fun onBackPressed() {
/*if (trulyGoBack) {
super.onBackPressed()
return
}*/
/*if (drawer.isDrawerOpen(GravityCompat.START) || drawer.isDrawerOpen(GravityCompat.END)) {
drawer.closeDrawers()
} else {*/
val baseController = router.backstack.last().controller() as? BaseController
if (if (router.backstackSize == 1) !(baseController?.handleRootBack() ?: false)
val sheetController = router.backstack.last().controller() as? BottomSheetController
if (if (router.backstackSize == 1) !(sheetController?.handleSheetBack() ?: false)
else !router.handleBack()
) {
SecureActivityDelegate.locked = true
super.onBackPressed()
}
// }
}
private fun setRoot(controller: Controller, id: Int) {
@ -484,8 +461,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
gestureDetector.onTouchEvent(ev)
val controller = router.backstack.lastOrNull()?.controller()
if (controller is OnTouchEventInterface) controller.onTouchEvent(ev)
if (ev?.action == MotionEvent.ACTION_DOWN) {
if (snackBar != null && snackBar!!.isShown) {
val sRect = Rect()
@ -530,10 +505,6 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
}
drawerArrow?.progress = 1f
currentGestureDelegate = to as? SwipeGestureInterface
if (to !is SpinnerTitleInterface) toolbar.removeSpinner()
if (to !is DialogController) {
bottom_nav.visibility =
if (router.backstackSize == 0 || (router.backstackSize <= 1 && !isPush)) View.VISIBLE else bottom_nav.visibility
@ -587,37 +558,21 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
velocityX: Float,
velocityY: Float
): Boolean {
if (currentGestureDelegate == null) return false
var result = false
try {
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (abs(diffX) > abs(diffY)) {
if (abs(diffX) > Companion.SWIPE_THRESHOLD && abs(velocityX) > Companion.SWIPE_VELOCITY_THRESHOLD && abs(
diffY
) <= Companion.SWIPE_THRESHOLD * 0.75f
) {
if (diffX > 0) {
currentGestureDelegate?.onSwipeRight(velocityX, e2.x)
} else {
currentGestureDelegate?.onSwipeLeft(velocityX, e2.x)
}
result = true
}
} else if (abs(diffY) > Companion.SWIPE_THRESHOLD && abs(
velocityY
) > Companion.SWIPE_VELOCITY_THRESHOLD
val diffY = e2.y - e1.y
val diffX = e2.x - e1.x
if (abs(diffX) <= abs(diffY)) {
val sheetRect = Rect()
bottom_nav.getGlobalVisibleRect(sheetRect)
if (sheetRect.contains(
e1.x.toInt(), e1.y.toInt()
) && abs(diffY) > Companion.SWIPE_THRESHOLD && abs(velocityY) > Companion.SWIPE_VELOCITY_THRESHOLD && diffY <= 0
) {
if (diffY > 0) {
currentGestureDelegate?.onSwipeBottom(e1.x, e1.y)
// onSwipeBottom()
} else {
currentGestureDelegate?.onSwipeTop(e1.x, e1.y)
}
result = true
val bottomSheetController =
router.backstack.lastOrNull()?.controller() as? BottomSheetController
bottomSheetController?.showSheet()
}
} catch (exception: Exception) {
exception.printStackTrace()
result = true
}
return result
}
@ -649,19 +604,13 @@ interface BottomNavBarInterface {
interface RootSearchInterface {
fun expandSearch() {
if (this is Controller) activity?.toolbar?.menu?.findItem(R.id.action_search)?.expandActionView()
if (this is Controller) activity?.toolbar?.menu?.findItem(R.id.action_search)
?.expandActionView()
}
}
interface SpinnerTitleInterface
interface OnTouchEventInterface {
fun onTouchEvent(event: MotionEvent?)
}
interface SwipeGestureInterface {
fun onSwipeRight(x: Float, xPos: Float)
fun onSwipeLeft(x: Float, xPos: Float)
fun onSwipeTop(x: Float, y: Float)
fun onSwipeBottom(x: Float, y: Float)
interface BottomSheetController {
fun showSheet()
fun toggleSheet()
fun handleSheetBack(): Boolean
}

View File

@ -51,7 +51,6 @@ class SearchActivity : MainActivity() {
toolbar.navigationIcon = drawerArrow
drawerArrow?.progress = 1f
if (to !is SpinnerTitleInterface) toolbar.removeSpinner()
bottom_nav.gone()
}

View File

@ -524,29 +524,10 @@ class MangaDetailsController : BaseController,
// Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapters_mat_single, popup.menu)
// Hide bookmark if bookmark
popup.menu.findItem(R.id.action_bookmark).isVisible = false // !item.bookmark
popup.menu.findItem(R.id.action_remove_bookmark).isVisible = false // item.bookmark
// Hide mark as unread when the chapter is unread
// if (!item.read && item.last_page_read == 0) {
popup.menu.findItem(R.id.action_mark_as_unread).isVisible = false
// }
// Hide mark as read when the chapter is read
// if (item.read) {
popup.menu.findItem(R.id.action_mark_as_read).isVisible = false
// }
// Set a listener so we are notified if a menu item is clicked
popup.setOnMenuItemClickListener { menuItem ->
val chapters = listOf(item)
when (menuItem.itemId) {
R.id.action_bookmark -> bookmarkChapters(chapters, true)
R.id.action_remove_bookmark -> bookmarkChapters(chapters, false)
R.id.action_mark_as_read -> markAsRead(chapters)
R.id.action_mark_previous_as_read -> markPreviousAsRead(item)
R.id.action_mark_as_unread -> markAsUnread(chapters)
}
true
}
@ -614,6 +595,7 @@ class MangaDetailsController : BaseController,
presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch
menu.findItem(R.id.action_mark_all_as_unread).isVisible =
!presenter.allUnread() && !presenter.isLockedFromSearch
menu.findItem(R.id.action_mark_all_as_unread).isVisible = presenter.isTracked()
val iconPrimary = view?.context?.getResourceColor(android.R.attr.textColorPrimary)
?: Color.BLACK
menu.findItem(R.id.action_download).icon?.mutate()?.setTint(iconPrimary)
@ -647,29 +629,24 @@ class MangaDetailsController : BaseController,
when (item.itemId) {
R.id.action_edit -> {
if (manga?.source == LocalSource.ID) {
editMangaDialog =
EditMangaDialog(
this,
presenter.manga
)
editMangaDialog = EditMangaDialog(
this, presenter.manga
)
editMangaDialog?.showDialog(router)
} else {
if (manga?.hasCustomCover() == true) {
MaterialDialog(activity!!).listItems(items = listOf(
view!!.context.getString(
R.string.action_edit_cover
), view!!.context.getString(
R.string.action_reset_cover
)
),
waitForPositiveButton = false,
selection = { _, index, _ ->
when (index) {
0 -> changeCover()
else -> presenter.clearCover()
}
})
.show()
view!!.context.getString(
R.string.action_edit_cover
), view!!.context.getString(
R.string.action_reset_cover
)
), waitForPositiveButton = false, selection = { _, index, _ ->
when (index) {
0 -> changeCover()
else -> presenter.clearCover()
}
}).show()
} else {
changeCover()
}
@ -678,19 +655,17 @@ class MangaDetailsController : BaseController,
R.id.action_open_in_web_view -> openInWebView()
R.id.action_share -> prepareToShareManga()
R.id.action_add_to_home_screen -> addToHomeScreen()
R.id.action_refresh_tracking -> presenter.refreshTrackers()
R.id.action_mark_all_as_read -> {
MaterialDialog(view!!.context)
.message(R.string.mark_all_as_read_message)
MaterialDialog(view!!.context).message(R.string.mark_all_as_read_message)
.positiveButton(R.string.action_mark_as_read) {
markAsRead(presenter.chapters)
}
.negativeButton(android.R.string.cancel)
.show()
}.negativeButton(android.R.string.cancel).show()
}
R.id.action_mark_all_as_unread -> markAsUnread(presenter.chapters)
R.id.download_next, R.id.download_next_5, R.id.download_next_10,
R.id.download_custom, R.id.download_unread, R.id.download_all
-> downloadChapters(item.itemId)
R.id.download_next, R.id.download_next_5, R.id.download_custom, R.id.download_unread, R.id.download_all -> downloadChapters(
item.itemId
)
else -> return super.onOptionsItemSelected(item)
}
return true
@ -759,7 +734,6 @@ class MangaDetailsController : BaseController,
val chaptersToDownload = when (choice) {
R.id.download_next -> presenter.getUnreadChaptersSorted().take(1)
R.id.download_next_5 -> presenter.getUnreadChaptersSorted().take(5)
R.id.download_next_10 -> presenter.getUnreadChaptersSorted().take(10)
R.id.download_custom -> {
createActionModeIfNeeded()
return

View File

@ -27,7 +27,6 @@ import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.view.scrollViewWith
import eu.kanade.tachiyomi.util.view.snack
import kotlinx.android.synthetic.main.download_bottom_sheet.*
import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.recent_chapters_controller.*
import kotlinx.android.synthetic.main.recent_chapters_controller.empty_view
import timber.log.Timber
@ -87,10 +86,7 @@ class RecentChaptersController(bundle: Bundle? = null) : BaseController(bundle),
swipe_refresh.setOnRefreshListener {
if (!LibraryUpdateService.isRunning()) {
LibraryUpdateService.start(view.context)
view.snack(R.string.updating_library) {
anchorView = (this@RecentChaptersController.activity as? MainActivity)
?.bottom_nav
}
snack = view.snack(R.string.updating_library)
}
// It can be a very long operation, so we disable swipe refresh and show a snackbar.
swipe_refresh.isRefreshing = false

View File

@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.main.RootSearchInterface
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
@ -53,7 +54,8 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
RecentMangaAdapter.RecentsInterface,
FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemMoveListener,
RootSearchInterface {
RootSearchInterface,
BottomSheetController {
init {
setHasOptionsMenu(true)
@ -182,7 +184,7 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
swipe_refresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_SWIPE
}
override fun handleRootBack(): Boolean {
override fun handleSheetBack(): Boolean {
if (dl_bottom_sheet.sheetBehavior?.state == BottomSheetBehavior.STATE_EXPANDED) {
dl_bottom_sheet.dismiss()
return true
@ -353,11 +355,11 @@ class RecentsController(bundle: Bundle? = null) : BaseController(bundle),
}
}
fun showDownloads() {
override fun showSheet() {
dl_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED
}
fun toggleDownloads() {
override fun toggleSheet() {
if (dl_bottom_sheet.sheetBehavior?.isHideable == false) {
if (showingDownloads) dl_bottom_sheet.dismiss()
else dl_bottom_sheet.sheetBehavior?.state = BottomSheetBehavior.STATE_EXPANDED

View File

@ -340,6 +340,7 @@ fun Controller.scrollViewWith(
val array = recycler.context.obtainStyledAttributes(attrsArray)
val appBarHeight = array.getDimensionPixelSize(0, 0)
array.recycle()
swipeRefreshLayout?.setDistanceToTriggerSync(150.dpToPx)
recycler.doOnApplyWindowInsets { view, insets, _ ->
val headerHeight = insets.systemWindowInsetTop + appBarHeight
if (!customPadding) view.updatePaddingRelative(

View File

@ -158,7 +158,7 @@
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:text="@string/auto_hide_category_seeker" />
android:text="@string/always_show_library_fast_scroll"/>
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_filters"

View File

@ -57,17 +57,6 @@
android:textColor="?actionBarTintColor"
android:textSize="20sp"
tools:text="Title Text" />
<ImageView
android:id="@+id/dropdown"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center"
android:layout_marginStart="4dp"
android:background="@drawable/round_ripple"
android:src="@drawable/ic_arrow_drop_down_white_24dp"
android:tint="?actionBarTintColor" />
</LinearLayout>
</eu.kanade.tachiyomi.ui.base.CenteredToolbar>

View File

@ -1,93 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_filter"
android:icon="@drawable/ic_filter_list_white_24dp"
android:title="@string/action_filter"
app:showAsAction="ifRoom">
<menu>
<item
android:id="@+id/action_filter_read"
android:checkable="true"
android:title="@string/action_filter_read"/>
<item
android:id="@+id/action_filter_unread"
android:checkable="true"
android:title="@string/action_filter_unread"/>
<item
android:id="@+id/action_filter_downloaded"
android:checkable="true"
android:title="@string/action_filter_downloaded"/>
<item
android:id="@+id/action_filter_bookmarked"
android:checkable="true"
android:title="@string/action_filter_bookmarked"/>
<item
android:id="@+id/action_filter_empty"
android:title="@string/action_filter_empty"/>
</menu>
</item>
<item
android:id="@+id/action_sort"
android:icon="@drawable/ic_sort_by_numeric_white_24dp"
android:title="@string/action_sort"
app:showAsAction="ifRoom"/>
<item
android:title="@string/action_display_mode"
app:showAsAction="never">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/display_title"
android:title="@string/show_title" />
<item
android:id="@+id/display_chapter_number"
android:title="@string/show_chapter_number" />
</group>
</menu>
</item>
<item
android:title="@string/sorting_mode"
app:showAsAction="never">
<menu>
<group android:checkableBehavior="single">
<item
android:id="@+id/sort_by_source"
android:title="@string/sort_by_source" />
<item
android:id="@+id/sort_by_number"
android:title="@string/sort_by_number" />
</group>
</menu>
</item>
<item
android:title="@string/manga_download"
app:showAsAction="never" >
<menu >
<item
android:id="@+id/download_next"
android:title="@string/download_1" />
<item
android:id="@+id/download_next_5"
android:title="@string/download_5" />
<item
android:id="@+id/download_next_10"
android:title="@string/download_10" />
<item
android:id="@+id/download_custom"
android:title="@string/download_custom" />
<item
android:id="@+id/download_unread"
android:title="@string/download_unread" />
<item
android:id="@+id/download_all"
android:title="@string/download_all" />
</menu>
</item>
</menu>

View File

@ -1,21 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_mark_as_read"
android:title="@string/action_mark_as_read" />
<item android:id="@+id/action_mark_as_unread"
android:title="@string/action_mark_as_unread" />
<item android:id="@+id/action_bookmark"
android:title="@string/action_bookmark"
android:visible="true" />
<item android:id="@+id/action_remove_bookmark"
android:title="@string/action_remove_bookmark"
android:visible="true" />
<item android:id="@+id/action_mark_previous_as_read"
android:title="@string/action_mark_previous_as_read"/>
</menu>

View File

@ -37,14 +37,19 @@
android:id="@+id/action_mark_all_as_read"
android:icon="@drawable/ic_done_all_white_24dp"
android:title="@string/action_mark_all_as_read"
app:showAsAction="never" />
app:showAsAction="ifRoom" />
<item
android:id="@+id/action_mark_all_as_unread"
android:icon="@drawable/ic_done_all_white_24dp"
android:title="@string/action_mark_all_as_unread"
app:showAsAction="never" />
<item
android:id="@+id/action_refresh_tracking"
android:icon="@drawable/ic_refresh_white_24dp"
android:title="@string/action_refresh_tracking"
app:showAsAction="never" />
<item
android:id="@+id/action_edit"
android:icon="@drawable/ic_edit_white_24dp"

View File

@ -81,6 +81,7 @@
<string name="action_mark_as_read">Mark as read</string>
<string name="action_mark_all_as_read">Mark all as read</string>
<string name="action_mark_all_as_unread">Mark all as unread</string>
<string name="action_refresh_tracking">Refresh tracking</string>
<string name="action_mark_as_unread">Mark as unread</string>
<string name="action_mark_previous_as_read">Mark previous as read</string>
<string name="action_mark_multiple">Mark multiple</string>
@ -122,7 +123,7 @@
<string name="action_display_grid">Compact Grid</string>
<string name="action_display_list">List</string>
<string name="action_display_download_badge">Download badges</string>
<string name="auto_hide_category_seeker">Auto-hide category seeker</string>
<string name="always_show_library_fast_scroll">Always show library fast scroll</string>
<string name="action_display_unread_badge">Unread badges</string>
<string name="action_set_filter">Set filter</string>
<string name="action_cancel">Cancel</string>
@ -209,6 +210,7 @@
<item quantity="one">%d category</item>
<item quantity="other">%d categories</item>
</plurals>
<string name="top">Top</string>
<string name="pref_category_library_update">Updates</string>
<string name="pref_library_update_interval">Library update frequency</string>