@ -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 a utoHideScroller: Boolean = preferences . autoHide Seeker( ) . 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 ( ! autoHide Scroller) return
if ( alwaysShow Scroller) 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 ( autoHide Scroller) ContextCompat . getDrawable (
fast _scroller . background = if ( ! alwaysShow Scroller) 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 ( autoHide Scroller) android . R . attr . textColorPrimaryInverse else android . R . attr . textColorPrimary
if ( ! alwaysShow Scroller) 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 = !is Dragging
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 = !is Dragging
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 ( ! autoHide Scroller) 2 else 5 ) . dpToPx ,
start = ( if ( alwaysShow Scroller) 2 else 5 ) . dpToPx ,
end = ( if ( ! autoHide Scroller) 12 else 5 ) . dpToPx
end = ( if ( alwaysShow Scroller) 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
}
}