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
pull/3117/head
Jay 5 years ago
parent 83206ded5e
commit 651682df4a

@ -177,7 +177,7 @@ class PreferencesHelper(val context: Context) {
fun gridSize() = rxPrefs.getInteger(Keys.gridSize, 1) 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) fun uniformGrid() = rxPrefs.getBoolean(Keys.uniformGrid, true)

@ -2,12 +2,8 @@ package eu.kanade.tachiyomi.ui.base
import android.content.Context import android.content.Context
import android.util.AttributeSet import android.util.AttributeSet
import android.view.Gravity
import androidx.appcompat.graphics.drawable.DrawerArrowDrawable import androidx.appcompat.graphics.drawable.DrawerArrowDrawable
import androidx.appcompat.widget.PopupMenu
import com.google.android.material.appbar.MaterialToolbar 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.* import kotlinx.android.synthetic.main.main_activity.view.*
class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@ -44,20 +40,4 @@ class CenteredToolbar@JvmOverloads constructor(context: Context, attrs: Attribut
super.setTitle(null) 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)
}
} }

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

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

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

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

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

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

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

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

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

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

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

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

@ -524,29 +524,10 @@ class MangaDetailsController : BaseController,
// Inflate our menu resource into the PopupMenu's Menu // Inflate our menu resource into the PopupMenu's Menu
popup.menuInflater.inflate(R.menu.chapters_mat_single, popup.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 -> popup.setOnMenuItemClickListener { menuItem ->
val chapters = listOf(item) val chapters = listOf(item)
when (menuItem.itemId) { 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_previous_as_read -> markPreviousAsRead(item)
R.id.action_mark_as_unread -> markAsUnread(chapters)
} }
true true
} }
@ -614,6 +595,7 @@ class MangaDetailsController : BaseController,
presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch presenter.getNextUnreadChapter() != null && !presenter.isLockedFromSearch
menu.findItem(R.id.action_mark_all_as_unread).isVisible = menu.findItem(R.id.action_mark_all_as_unread).isVisible =
!presenter.allUnread() && !presenter.isLockedFromSearch !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) val iconPrimary = view?.context?.getResourceColor(android.R.attr.textColorPrimary)
?: Color.BLACK ?: Color.BLACK
menu.findItem(R.id.action_download).icon?.mutate()?.setTint(iconPrimary) menu.findItem(R.id.action_download).icon?.mutate()?.setTint(iconPrimary)
@ -647,10 +629,8 @@ class MangaDetailsController : BaseController,
when (item.itemId) { when (item.itemId) {
R.id.action_edit -> { R.id.action_edit -> {
if (manga?.source == LocalSource.ID) { if (manga?.source == LocalSource.ID) {
editMangaDialog = editMangaDialog = EditMangaDialog(
EditMangaDialog( this, presenter.manga
this,
presenter.manga
) )
editMangaDialog?.showDialog(router) editMangaDialog?.showDialog(router)
} else { } else {
@ -661,15 +641,12 @@ class MangaDetailsController : BaseController,
), view!!.context.getString( ), view!!.context.getString(
R.string.action_reset_cover R.string.action_reset_cover
) )
), ), waitForPositiveButton = false, selection = { _, index, _ ->
waitForPositiveButton = false,
selection = { _, index, _ ->
when (index) { when (index) {
0 -> changeCover() 0 -> changeCover()
else -> presenter.clearCover() else -> presenter.clearCover()
} }
}) }).show()
.show()
} else { } else {
changeCover() changeCover()
} }
@ -678,19 +655,17 @@ class MangaDetailsController : BaseController,
R.id.action_open_in_web_view -> openInWebView() R.id.action_open_in_web_view -> openInWebView()
R.id.action_share -> prepareToShareManga() R.id.action_share -> prepareToShareManga()
R.id.action_add_to_home_screen -> addToHomeScreen() R.id.action_add_to_home_screen -> addToHomeScreen()
R.id.action_refresh_tracking -> presenter.refreshTrackers()
R.id.action_mark_all_as_read -> { R.id.action_mark_all_as_read -> {
MaterialDialog(view!!.context) MaterialDialog(view!!.context).message(R.string.mark_all_as_read_message)
.message(R.string.mark_all_as_read_message)
.positiveButton(R.string.action_mark_as_read) { .positiveButton(R.string.action_mark_as_read) {
markAsRead(presenter.chapters) 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.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_next, R.id.download_next_5, R.id.download_custom, R.id.download_unread, R.id.download_all -> downloadChapters(
R.id.download_custom, R.id.download_unread, R.id.download_all item.itemId
-> downloadChapters(item.itemId) )
else -> return super.onOptionsItemSelected(item) else -> return super.onOptionsItemSelected(item)
} }
return true return true
@ -759,7 +734,6 @@ class MangaDetailsController : BaseController,
val chaptersToDownload = when (choice) { val chaptersToDownload = when (choice) {
R.id.download_next -> presenter.getUnreadChaptersSorted().take(1) R.id.download_next -> presenter.getUnreadChaptersSorted().take(1)
R.id.download_next_5 -> presenter.getUnreadChaptersSorted().take(5) R.id.download_next_5 -> presenter.getUnreadChaptersSorted().take(5)
R.id.download_next_10 -> presenter.getUnreadChaptersSorted().take(10)
R.id.download_custom -> { R.id.download_custom -> {
createActionModeIfNeeded() createActionModeIfNeeded()
return return

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

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

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

@ -158,7 +158,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:layout_marginEnd="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 <com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/hide_filters" android:id="@+id/hide_filters"

@ -57,17 +57,6 @@
android:textColor="?actionBarTintColor" android:textColor="?actionBarTintColor"
android:textSize="20sp" android:textSize="20sp"
tools:text="Title Text" /> 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> </LinearLayout>
</eu.kanade.tachiyomi.ui.base.CenteredToolbar> </eu.kanade.tachiyomi.ui.base.CenteredToolbar>

@ -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>

@ -1,21 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <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" <item android:id="@+id/action_mark_previous_as_read"
android:title="@string/action_mark_previous_as_read"/> android:title="@string/action_mark_previous_as_read"/>
</menu> </menu>

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

@ -81,6 +81,7 @@
<string name="action_mark_as_read">Mark as read</string> <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_read">Mark all as read</string>
<string name="action_mark_all_as_unread">Mark all as unread</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_as_unread">Mark as unread</string>
<string name="action_mark_previous_as_read">Mark previous as read</string> <string name="action_mark_previous_as_read">Mark previous as read</string>
<string name="action_mark_multiple">Mark multiple</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_grid">Compact Grid</string>
<string name="action_display_list">List</string> <string name="action_display_list">List</string>
<string name="action_display_download_badge">Download badges</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_display_unread_badge">Unread badges</string>
<string name="action_set_filter">Set filter</string> <string name="action_set_filter">Set filter</string>
<string name="action_cancel">Cancel</string> <string name="action_cancel">Cancel</string>
@ -209,6 +210,7 @@
<item quantity="one">%d category</item> <item quantity="one">%d category</item>
<item quantity="other">%d categories</item> <item quantity="other">%d categories</item>
</plurals> </plurals>
<string name="top">Top</string>
<string name="pref_category_library_update">Updates</string> <string name="pref_category_library_update">Updates</string>
<string name="pref_library_update_interval">Library update frequency</string> <string name="pref_library_update_interval">Library update frequency</string>

Loading…
Cancel
Save