mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-14 05:15:10 +01:00
Using new (old?) fast scroller in library
New category jumper now shows what catergory you're on while scrolling
This commit is contained in:
parent
a9ec02caac
commit
de8cb8c1b0
@ -177,8 +177,6 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun gridSize() = rxPrefs.getInteger(Keys.gridSize, 2)
|
fun gridSize() = rxPrefs.getInteger(Keys.gridSize, 2)
|
||||||
|
|
||||||
fun alwaysShowSeeker() = rxPrefs.getBoolean("always_show_seeker", false)
|
|
||||||
|
|
||||||
fun uniformGrid() = rxPrefs.getBoolean(Keys.uniformGrid, true)
|
fun uniformGrid() = rxPrefs.getBoolean(Keys.uniformGrid, true)
|
||||||
|
|
||||||
fun chaptersDescAsDefault() = rxPrefs.getBoolean("chapters_desc_as_default", true)
|
fun chaptersDescAsDefault() = rxPrefs.getBoolean("chapters_desc_as_default", true)
|
||||||
|
@ -85,9 +85,6 @@ 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.alwaysShowSeeker()) {
|
|
||||||
controller.updateShowScrollbar(autohide_seeker.isChecked)
|
|
||||||
}
|
|
||||||
grid_size_toggle_group.bindToPreference(preferences.gridSize()) {
|
grid_size_toggle_group.bindToPreference(preferences.gridSize()) {
|
||||||
controller.reattachAdapter()
|
controller.reattachAdapter()
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ 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.removeArticles
|
import eu.kanade.tachiyomi.util.lang.removeArticles
|
||||||
|
import eu.kanade.tachiyomi.util.system.timeSpanFromNow
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapter storing a list of manga in a certain category.
|
* Adapter storing a list of manga in a certain category.
|
||||||
@ -98,57 +98,63 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
|||||||
isLongPressDragEnabled = libraryListener.canDrag() && s.isNullOrBlank()
|
isLongPressDragEnabled = libraryListener.canDrag() && s.isNullOrBlank()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSectionText(position: Int): String? {
|
private fun getFirstLetter(name: String): String {
|
||||||
|
val letter = name.firstOrNull() ?: '#'
|
||||||
|
return if (letter.isLetter()) getFirstChar(name) else "#"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateBubbleText(position: Int): String {
|
||||||
val preferences: PreferencesHelper by injectLazy()
|
val preferences: PreferencesHelper by injectLazy()
|
||||||
val db: DatabaseHelper by injectLazy()
|
val db: DatabaseHelper by injectLazy()
|
||||||
if (position == itemCount - 1) return "-"
|
if (position == itemCount - 1) return recyclerView.context.getString(R.string.bottom)
|
||||||
val sorting = if (!preferences.showAllCategories().get()) {
|
|
||||||
controller.presenter.getCurrentCategory()?.sortingMode() ?: LibrarySort.DRAG_AND_DROP
|
|
||||||
} else if (preferences.hideCategories().getOrDefault()) {
|
|
||||||
preferences.librarySortingMode().getOrDefault()
|
|
||||||
} else {
|
|
||||||
(headerItems.firstOrNull() as? LibraryHeaderItem)?.category?.sortingMode()
|
|
||||||
?: LibrarySort.DRAG_AND_DROP
|
|
||||||
}
|
|
||||||
return when (val item: IFlexible<*>? = getItem(position)) {
|
return when (val item: IFlexible<*>? = getItem(position)) {
|
||||||
is LibraryHeaderItem ->
|
is LibraryHeaderItem ->
|
||||||
if (preferences.hideCategories().getOrDefault() || item.category.id == 0 ||
|
if (!preferences.hideCategories().getOrDefault()) item.category.name
|
||||||
!preferences.showAllCategories().get()) null
|
else recyclerView.context.getString(R.string.top)
|
||||||
else getFirstChar(item.category.name) +
|
|
||||||
"\u200B".repeat(max(0, item.category.order))
|
|
||||||
is LibraryItem -> {
|
is LibraryItem -> {
|
||||||
when (sorting) {
|
if (!isSingleCategory) {
|
||||||
|
item.header?.category?.name.orEmpty()
|
||||||
|
} else if (item.manga.isBlank()) ""
|
||||||
|
else when (getSort()) {
|
||||||
LibrarySort.DRAG_AND_DROP -> {
|
LibrarySort.DRAG_AND_DROP -> {
|
||||||
val category = db.getCategoriesForManga(item.manga).executeAsBlocking()
|
if (!preferences.hideCategories().getOrDefault()) {
|
||||||
.firstOrNull()
|
val title = item.manga.title
|
||||||
if (category == null) null
|
if (preferences.removeArticles().getOrDefault())
|
||||||
else getFirstLetter(category.name) + "\u200B".repeat(max(0, category.order))
|
getFirstChar(title.removeArticles())
|
||||||
|
else getFirstChar(title)
|
||||||
|
} else {
|
||||||
|
val category = db.getCategoriesForManga(item.manga)
|
||||||
|
.executeAsBlocking().firstOrNull()?.name
|
||||||
|
category ?: recyclerView.context.getString(R.string.default_value)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
LibrarySort.LAST_READ -> {
|
LibrarySort.LAST_READ -> {
|
||||||
val id = item.manga.id ?: return ""
|
val id = item.manga.id ?: return ""
|
||||||
val history = db.getHistoryByMangaId(id).executeAsBlocking()
|
val history = db.getHistoryByMangaId(id).executeAsBlocking()
|
||||||
val last = history.maxBy { it.last_read }
|
val last = history.maxBy { it.last_read }
|
||||||
if (last != null && last.last_read > 100) getShorterDate(Date(last.last_read))
|
if (last != null && last.last_read > 100) last.last_read.timeSpanFromNow
|
||||||
else "*"
|
else "N/A"
|
||||||
}
|
|
||||||
LibrarySort.TOTAL -> {
|
|
||||||
val unread = item.chapterCount
|
|
||||||
getShortRange(unread)
|
|
||||||
}
|
}
|
||||||
LibrarySort.UNREAD -> {
|
LibrarySort.UNREAD -> {
|
||||||
val unread = item.manga.unread
|
val unread = item.manga.unread
|
||||||
if (unread > 0) getShortRange(unread)
|
if (unread > 0) unread.toString()
|
||||||
else "R"
|
else recyclerView.context.getString(R.string.read)
|
||||||
|
}
|
||||||
|
LibrarySort.TOTAL -> {
|
||||||
|
val total = item.chapterCount
|
||||||
|
if (total > 0) total.toString()
|
||||||
|
else "N/A"
|
||||||
}
|
}
|
||||||
LibrarySort.LATEST_CHAPTER -> {
|
LibrarySort.LATEST_CHAPTER -> {
|
||||||
val lastUpdate = item.manga.last_update
|
val lastUpdate = item.manga.last_update
|
||||||
if (lastUpdate > 0) getShorterDate(Date(lastUpdate))
|
if (lastUpdate > 0) lastUpdate.timeSpanFromNow
|
||||||
else "*"
|
// getShortDate(Date(lastUpdate))
|
||||||
|
else "N/A"
|
||||||
}
|
}
|
||||||
LibrarySort.DATE_ADDED -> {
|
LibrarySort.DATE_ADDED -> {
|
||||||
val lastUpdate = item.manga.date_added
|
val lastUpdate = item.manga.date_added
|
||||||
if (lastUpdate > 0) getShorterDate(Date(lastUpdate))
|
if (lastUpdate > 0) lastUpdate.timeSpanFromNow
|
||||||
else "*"
|
else "N/A"
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
val title = if (preferences.removeArticles()
|
val title = if (preferences.removeArticles()
|
||||||
@ -163,67 +169,12 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFirstLetter(name: String): String {
|
private fun getSort(): Int {
|
||||||
val letter = name.firstOrNull() ?: '#'
|
|
||||||
return if (letter.isLetter()) getFirstChar(name) else "#"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateBubbleText(position: Int): String {
|
|
||||||
val preferences: PreferencesHelper by injectLazy()
|
val preferences: PreferencesHelper by injectLazy()
|
||||||
val db: DatabaseHelper by injectLazy()
|
return if (!preferences.showAllCategories().get() && !preferences.hideCategories().getOrDefault()) {
|
||||||
if (position == itemCount - 1) return recyclerView.context.getString(R.string.bottom)
|
|
||||||
return when (val iFlexible: IFlexible<*>? = getItem(position)) {
|
|
||||||
is LibraryHeaderItem ->
|
|
||||||
if (!preferences.hideCategories().getOrDefault()) iFlexible.category.name
|
|
||||||
else recyclerView.context.getString(R.string.top)
|
|
||||||
is LibraryItem -> {
|
|
||||||
if (iFlexible.manga.isBlank()) ""
|
|
||||||
else when (if (!preferences.showAllCategories().get()) {
|
|
||||||
controller.presenter.getCurrentCategory()?.sortingMode() ?: LibrarySort.DRAG_AND_DROP
|
controller.presenter.getCurrentCategory()?.sortingMode() ?: LibrarySort.DRAG_AND_DROP
|
||||||
} else preferences.librarySortingMode().getOrDefault()) {
|
|
||||||
LibrarySort.DRAG_AND_DROP -> {
|
|
||||||
if (!preferences.hideCategories().getOrDefault()) {
|
|
||||||
val title = iFlexible.manga.title
|
|
||||||
if (preferences.removeArticles().getOrDefault())
|
|
||||||
getFirstChar(title.removeArticles())
|
|
||||||
else getFirstChar(title)
|
|
||||||
} else {
|
} else {
|
||||||
val category = db.getCategoriesForManga(iFlexible.manga)
|
preferences.librarySortingMode().getOrDefault()
|
||||||
.executeAsBlocking().firstOrNull()?.name
|
|
||||||
category ?: recyclerView.context.getString(R.string.default_value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LibrarySort.LAST_READ -> {
|
|
||||||
val id = iFlexible.manga.id ?: return ""
|
|
||||||
val history = db.getHistoryByMangaId(id).executeAsBlocking()
|
|
||||||
val last = history.maxBy { it.last_read }
|
|
||||||
if (last != null && last.last_read > 100) getShortDate(Date(last.last_read))
|
|
||||||
else "N/A"
|
|
||||||
}
|
|
||||||
LibrarySort.UNREAD -> {
|
|
||||||
val unread = iFlexible.manga.unread
|
|
||||||
if (unread > 0) getRange(unread)
|
|
||||||
else recyclerView.context.getString(R.string.read)
|
|
||||||
}
|
|
||||||
LibrarySort.TOTAL -> {
|
|
||||||
val total = iFlexible.chapterCount
|
|
||||||
if (total > 0) getRange(total)
|
|
||||||
else "N/A"
|
|
||||||
}
|
|
||||||
LibrarySort.LATEST_CHAPTER -> {
|
|
||||||
val lastUpdate = iFlexible.manga.last_update
|
|
||||||
if (lastUpdate > 0) getShortDate(Date(lastUpdate))
|
|
||||||
else "N/A"
|
|
||||||
}
|
|
||||||
LibrarySort.DATE_ADDED -> {
|
|
||||||
val lastUpdate = iFlexible.manga.date_added
|
|
||||||
if (lastUpdate > 0) getShortDate(Date(lastUpdate))
|
|
||||||
else "N/A"
|
|
||||||
}
|
|
||||||
else -> getSectionText(position) ?: ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> ""
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,23 +205,6 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getRange(value: Int): String {
|
|
||||||
return when (value) {
|
|
||||||
1 -> "1"
|
|
||||||
2 -> "2"
|
|
||||||
3 -> "3"
|
|
||||||
4 -> "4"
|
|
||||||
5 -> "5"
|
|
||||||
in 6..10 -> "6-10"
|
|
||||||
in 11..50 -> "11-50"
|
|
||||||
in 51..100 -> "51-100"
|
|
||||||
in 101..500 -> "100-500"
|
|
||||||
in 499..899 -> "499-900"
|
|
||||||
in 901..Int.MAX_VALUE -> "900+"
|
|
||||||
else -> "None"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getShorterDate(date: Date): String {
|
private fun getShorterDate(date: Date): String {
|
||||||
val cal = Calendar.getInstance()
|
val cal = Calendar.getInstance()
|
||||||
cal.time = Date()
|
cal.time = Date()
|
||||||
@ -286,25 +220,7 @@ class LibraryCategoryAdapter(val controller: LibraryController) :
|
|||||||
SimpleDateFormat("''yy", Locale.getDefault()).format(date)
|
SimpleDateFormat("''yy", Locale.getDefault()).format(date)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getShortDate(date: Date): String {
|
|
||||||
val cal = Calendar.getInstance()
|
|
||||||
cal.time = Date()
|
|
||||||
|
|
||||||
val yearNow = cal.get(Calendar.YEAR)
|
|
||||||
val cal2 = Calendar.getInstance()
|
|
||||||
cal2.time = date
|
|
||||||
val yearThen = cal2.get(Calendar.YEAR)
|
|
||||||
|
|
||||||
return if (yearNow == yearThen)
|
|
||||||
SimpleDateFormat("MMMM", Locale.getDefault()).format(date)
|
|
||||||
else
|
|
||||||
SimpleDateFormat("yyyy", Locale.getDefault()).format(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LibraryListener {
|
interface LibraryListener {
|
||||||
/**
|
|
||||||
* Called when an item of the list is released.
|
|
||||||
*/
|
|
||||||
fun startReading(position: Int)
|
fun startReading(position: Int)
|
||||||
fun onItemReleased(position: Int)
|
fun onItemReleased(position: Int)
|
||||||
fun canDrag(): Boolean
|
fun canDrag(): Boolean
|
||||||
|
@ -33,8 +33,6 @@ import com.bluelinelabs.conductor.ControllerChangeType
|
|||||||
import com.github.florent37.viewtooltip.ViewTooltip
|
import com.github.florent37.viewtooltip.ViewTooltip
|
||||||
import com.google.android.material.snackbar.BaseTransientBottomBar
|
import com.google.android.material.snackbar.BaseTransientBottomBar
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import com.reddit.indicatorfastscroll.FastScrollItemIndicator
|
|
||||||
import com.reddit.indicatorfastscroll.FastScrollerView
|
|
||||||
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.IFlexible
|
import eu.davidea.flexibleadapter.items.IFlexible
|
||||||
@ -59,7 +57,6 @@ 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.reader.ReaderActivity
|
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||||
import eu.kanade.tachiyomi.util.system.dpToPxEnd
|
|
||||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
import eu.kanade.tachiyomi.util.view.applyWindowInsetsForRootController
|
||||||
@ -71,11 +68,8 @@ import eu.kanade.tachiyomi.util.view.hide
|
|||||||
import eu.kanade.tachiyomi.util.view.isExpanded
|
import eu.kanade.tachiyomi.util.view.isExpanded
|
||||||
import eu.kanade.tachiyomi.util.view.isHidden
|
import eu.kanade.tachiyomi.util.view.isHidden
|
||||||
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
import eu.kanade.tachiyomi.util.view.scrollViewWith
|
||||||
import eu.kanade.tachiyomi.util.view.setBackground
|
|
||||||
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
import eu.kanade.tachiyomi.util.view.setOnQueryTextChangeListener
|
||||||
import eu.kanade.tachiyomi.util.view.setStartTranslationX
|
|
||||||
import eu.kanade.tachiyomi.util.view.setStyle
|
import eu.kanade.tachiyomi.util.view.setStyle
|
||||||
import eu.kanade.tachiyomi.util.view.show
|
|
||||||
import eu.kanade.tachiyomi.util.view.snack
|
import eu.kanade.tachiyomi.util.view.snack
|
||||||
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
import eu.kanade.tachiyomi.util.view.updateLayoutParams
|
||||||
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
import eu.kanade.tachiyomi.util.view.updatePaddingRelative
|
||||||
@ -156,11 +150,24 @@ class LibraryController(
|
|||||||
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
|
var hopperGravity: Int = preferences.hopperGravity().get()
|
||||||
private var alwaysShowScroller: Boolean = preferences.alwaysShowSeeker().getOrDefault()
|
set(value) {
|
||||||
|
field = value
|
||||||
|
if (category_hopper_frame == null) return
|
||||||
|
jumper_category_text.updateLayoutParams<CoordinatorLayout.LayoutParams> {
|
||||||
|
anchorGravity = when (value) {
|
||||||
|
0 -> Gravity.RIGHT or Gravity.CENTER_VERTICAL
|
||||||
|
2 -> Gravity.LEFT or Gravity.CENTER_VERTICAL
|
||||||
|
else -> Gravity.TOP or Gravity.CENTER_HORIZONTAL
|
||||||
|
}
|
||||||
|
gravity = anchorGravity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private var filterTooltip: ViewTooltip? = null
|
private var filterTooltip: ViewTooltip? = null
|
||||||
private var elevationAnim: ValueAnimator? = null
|
private var elevationAnim: ValueAnimator? = null
|
||||||
private var elevate = false
|
private var elevate = false
|
||||||
|
|
||||||
override fun getTitle(): String? {
|
override fun getTitle(): String? {
|
||||||
return view?.context?.getString(R.string.library)
|
return view?.context?.getString(R.string.library)
|
||||||
}
|
}
|
||||||
@ -191,42 +198,18 @@ class LibraryController(
|
|||||||
setActiveCategory()
|
setActiveCategory()
|
||||||
if (presenter.categories.size > 1 && dy != 0 && recyclerView.translationY == 0f) {
|
if (presenter.categories.size > 1 && dy != 0 && recyclerView.translationY == 0f) {
|
||||||
val headerItem = getHeader() ?: return
|
val headerItem = getHeader() ?: return
|
||||||
val view = fast_scroller ?: return
|
showCategoryText(headerItem.category.name)
|
||||||
|
|
||||||
val height = if (view.childCount > 0) {
|
|
||||||
view.height - (view.getChildAt(0)?.paddingTop
|
|
||||||
?: 0) - (view.getChildAt(view.childCount - 1)?.paddingBottom ?: 0)
|
|
||||||
} else {
|
|
||||||
view.height
|
|
||||||
}
|
|
||||||
val index = adapter.headerItems.indexOf(headerItem)
|
|
||||||
textAnim?.cancel()
|
|
||||||
textAnim = text_view_m.animate().alpha(0f).setDuration(250L).setStartDelay(2000)
|
|
||||||
textAnim?.start()
|
|
||||||
|
|
||||||
// fastScroll height * indicator position - center text - fastScroll padding
|
|
||||||
text_view_m.translationY =
|
|
||||||
height * (index.toFloat() / (adapter.headerItems.size + 1))
|
|
||||||
-text_view_m.height / 2 + 16.dpToPx
|
|
||||||
text_view_m.translationX = 45f.dpToPxEnd
|
|
||||||
text_view_m.alpha = 1f
|
|
||||||
text_view_m.text = headerItem.category.name
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
|
||||||
super.onScrollStateChanged(recyclerView, newState)
|
super.onScrollStateChanged(recyclerView, newState)
|
||||||
if (alwaysShowScroller) return
|
|
||||||
when (newState) {
|
when (newState) {
|
||||||
RecyclerView.SCROLL_STATE_DRAGGING -> {
|
RecyclerView.SCROLL_STATE_DRAGGING -> {
|
||||||
scrollAnim?.cancel()
|
fast_scroller.showScrollbar()
|
||||||
if (fast_scroller?.translationX != 0f) {
|
|
||||||
fast_scroller?.show()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
RecyclerView.SCROLL_STATE_IDLE -> {
|
RecyclerView.SCROLL_STATE_IDLE -> {
|
||||||
scrollAnim = fast_scroller?.hide()
|
|
||||||
val shortAnimationDuration = resources?.getInteger(
|
val shortAnimationDuration = resources?.getInteger(
|
||||||
android.R.integer.config_shortAnimTime
|
android.R.integer.config_shortAnimTime
|
||||||
) ?: 0
|
) ?: 0
|
||||||
@ -241,9 +224,17 @@ class LibraryController(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun showCategoryText(name: String) {
|
||||||
|
textAnim?.cancel()
|
||||||
|
textAnim = jumper_category_text.animate().alpha(0f).setDuration(250L).setStartDelay(2000)
|
||||||
|
textAnim?.start()
|
||||||
|
jumper_category_text.alpha = 1f
|
||||||
|
jumper_category_text.text = name
|
||||||
|
}
|
||||||
|
|
||||||
fun isAtTop(): Boolean {
|
fun isAtTop(): Boolean {
|
||||||
return if (presenter.showAllCategories) {
|
return if (presenter.showAllCategories) {
|
||||||
getVisibleHeader() == adapter.headerItems.firstOrNull()
|
!recycler.canScrollVertically(-1)
|
||||||
} else {
|
} else {
|
||||||
getVisibleHeader()?.category?.id == presenter.categories.firstOrNull()?.id
|
getVisibleHeader()?.category?.id == presenter.categories.firstOrNull()?.id
|
||||||
}
|
}
|
||||||
@ -251,7 +242,7 @@ class LibraryController(
|
|||||||
|
|
||||||
fun isAtBottom(): Boolean {
|
fun isAtBottom(): Boolean {
|
||||||
return if (presenter.showAllCategories) {
|
return if (presenter.showAllCategories) {
|
||||||
getVisibleHeader() == adapter.headerItems.lastOrNull()
|
!recycler.canScrollVertically(1)
|
||||||
} else {
|
} else {
|
||||||
getVisibleHeader()?.category?.id == presenter.categories.lastOrNull()?.id
|
getVisibleHeader()?.category?.id == presenter.categories.lastOrNull()?.id
|
||||||
}
|
}
|
||||||
@ -283,13 +274,10 @@ class LibraryController(
|
|||||||
super.onViewCreated(view)
|
super.onViewCreated(view)
|
||||||
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
|
view.applyWindowInsetsForRootController(activity!!.bottom_nav)
|
||||||
if (!::presenter.isInitialized) presenter = LibraryPresenter(this)
|
if (!::presenter.isInitialized) presenter = LibraryPresenter(this)
|
||||||
fast_scroller.setStartTranslationX(!alwaysShowScroller)
|
|
||||||
fast_scroller.setBackground(!alwaysShowScroller)
|
|
||||||
|
|
||||||
adapter = LibraryCategoryAdapter(this)
|
adapter = LibraryCategoryAdapter(this)
|
||||||
adapter.expandItemsAtStartUp()
|
|
||||||
adapter.isRecursiveCollapse = true
|
|
||||||
setRecyclerLayout()
|
setRecyclerLayout()
|
||||||
|
|
||||||
recycler.manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() {
|
recycler.manager.spanSizeLookup = (object : GridLayoutManager.SpanSizeLookup() {
|
||||||
override fun getSpanSize(position: Int): Int {
|
override fun getSpanSize(position: Int): Int {
|
||||||
if (libraryLayout == 0) return 1
|
if (libraryLayout == 0) return 1
|
||||||
@ -301,73 +289,12 @@ class LibraryController(
|
|||||||
})
|
})
|
||||||
recycler.setHasFixedSize(true)
|
recycler.setHasFixedSize(true)
|
||||||
recycler.adapter = adapter
|
recycler.adapter = adapter
|
||||||
fast_scroller.setupWithRecyclerView(recycler, { position ->
|
|
||||||
val letter = adapter.getSectionText(position)
|
fast_scroller.addOnScrollStateChangeListener {
|
||||||
if (!singleCategory && presenter.showAllCategories && !adapter.isHeader(
|
swipe_refresh.isEnabled = !it
|
||||||
adapter.getItem(
|
|
||||||
position
|
|
||||||
)
|
|
||||||
) && position != adapter.itemCount - 1
|
|
||||||
) null
|
|
||||||
else if (letter != null) FastScrollItemIndicator.Text(letter)
|
|
||||||
else FastScrollItemIndicator.Icon(R.drawable.ic_star_24dp)
|
|
||||||
})
|
|
||||||
fast_scroller.useDefaultScroller = false
|
|
||||||
fast_scroller.itemIndicatorSelectedCallbacks += object :
|
|
||||||
FastScrollerView.ItemIndicatorSelectedCallback {
|
|
||||||
override fun onItemIndicatorSelected(
|
|
||||||
indicator: FastScrollItemIndicator,
|
|
||||||
indicatorCenterY: Int,
|
|
||||||
itemPosition: Int
|
|
||||||
) {
|
|
||||||
fast_scroller.translationX = 0f
|
|
||||||
if (!alwaysShowScroller) {
|
|
||||||
scrollAnim?.cancel()
|
|
||||||
scrollAnim = fast_scroller.hide(2000)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
textAnim?.cancel()
|
adapter.fastScroller = fast_scroller
|
||||||
textAnim = text_view_m.animate().alpha(0f).setDuration(250L).setStartDelay(2000)
|
|
||||||
textAnim?.start()
|
|
||||||
|
|
||||||
text_view_m.translationY = indicatorCenterY.toFloat() - text_view_m.height / 2
|
|
||||||
text_view_m.translationX = 0f
|
|
||||||
text_view_m.alpha = 1f
|
|
||||||
text_view_m.text = adapter.onCreateBubbleText(itemPosition)
|
|
||||||
val appbar = activity?.appbar
|
|
||||||
|
|
||||||
if (singleCategory) {
|
|
||||||
val order = when (val item = adapter.getItem(itemPosition)) {
|
|
||||||
is LibraryHeaderItem -> item
|
|
||||||
is LibraryItem -> item.header
|
|
||||||
else -> null
|
|
||||||
}?.category?.order
|
|
||||||
if (order != null) {
|
|
||||||
activeCategory = order
|
|
||||||
preferences.lastUsedCategory().set(order)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
appbar?.y = 0f
|
|
||||||
val item = adapter.getItem(itemPosition)
|
|
||||||
if (item is LibraryHeaderItem) {
|
|
||||||
scrollToHeader(item.category.order)
|
|
||||||
} else {
|
|
||||||
recycler.suppressLayout(true)
|
|
||||||
(recycler.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(
|
|
||||||
itemPosition, if (adapter.isSingleCategory) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
if (itemPosition == 0) {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
(-40).dpToPx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
recycler.suppressLayout(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
recycler.addOnScrollListener(scrollListener)
|
recycler.addOnScrollListener(scrollListener)
|
||||||
|
|
||||||
val tv = TypedValue()
|
val tv = TypedValue()
|
||||||
@ -418,6 +345,7 @@ class LibraryController(
|
|||||||
else -> Gravity.CENTER
|
else -> Gravity.CENTER
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
hopperGravity = preferences.hopperGravity().get()
|
||||||
|
|
||||||
val gestureDetector = GestureDetectorCompat(activity, LibraryGestureDetector(this))
|
val gestureDetector = GestureDetectorCompat(activity, LibraryGestureDetector(this))
|
||||||
listOf(category_hopper_layout, up_category, down_category, category_button).forEach {
|
listOf(category_hopper_layout, up_category, down_category, category_button).forEach {
|
||||||
@ -430,9 +358,9 @@ class LibraryController(
|
|||||||
category_layout?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
category_layout?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
topMargin = recycler?.paddingTop ?: 0
|
topMargin = recycler?.paddingTop ?: 0
|
||||||
}
|
}
|
||||||
fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
// fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
||||||
topMargin = insets.systemWindowInsetTop
|
// topMargin = insets.systemWindowInsetTop
|
||||||
}
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
swipe_refresh.setOnRefreshListener {
|
swipe_refresh.setOnRefreshListener {
|
||||||
@ -509,9 +437,10 @@ class LibraryController(
|
|||||||
} else {
|
} else {
|
||||||
newOffset < adapter.headerItems.size
|
newOffset < adapter.headerItems.size
|
||||||
}) {
|
}) {
|
||||||
val newOrder =
|
val newCategory = (adapter.headerItems[newOffset] as LibraryHeaderItem).category
|
||||||
(adapter.headerItems[newOffset] as LibraryHeaderItem).category.order
|
val newOrder = newCategory.order
|
||||||
scrollToHeader(newOrder)
|
scrollToHeader(newOrder)
|
||||||
|
showCategoryText(newCategory.name)
|
||||||
} else {
|
} else {
|
||||||
recycler.scrollToPosition(if (next) adapter.itemCount - 1 else 0)
|
recycler.scrollToPosition(if (next) adapter.itemCount - 1 else 0)
|
||||||
}
|
}
|
||||||
@ -525,8 +454,10 @@ class LibraryController(
|
|||||||
newOffset < presenter.categories.size
|
newOffset < presenter.categories.size
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
val newOrder = presenter.categories[newOffset].order
|
val newCategory = presenter.categories[newOffset]
|
||||||
|
val newOrder = newCategory.order
|
||||||
scrollToHeader(newOrder)
|
scrollToHeader(newOrder)
|
||||||
|
showCategoryText(newCategory.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,16 +517,6 @@ class LibraryController(
|
|||||||
return order
|
return order
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateShowScrollbar(show: Boolean) {
|
|
||||||
alwaysShowScroller = show
|
|
||||||
fast_scroller?.setBackground(!show)
|
|
||||||
if (libraryLayout == 0) reattachAdapter()
|
|
||||||
scrollAnim?.cancel()
|
|
||||||
if (show) fast_scroller?.translationX = 0f
|
|
||||||
else scrollAnim = fast_scroller?.hide()
|
|
||||||
setRecyclerLayout()
|
|
||||||
}
|
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
@ -627,8 +548,8 @@ class LibraryController(
|
|||||||
else -> .75f
|
else -> .75f
|
||||||
}
|
}
|
||||||
recycler.updatePaddingRelative(
|
recycler.updatePaddingRelative(
|
||||||
start = (if (alwaysShowScroller) 2 else 5).dpToPx,
|
start = 5.dpToPx,
|
||||||
end = (if (alwaysShowScroller) 12 else 5).dpToPx
|
end = 5.dpToPx
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -684,7 +605,7 @@ class LibraryController(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onNextLibraryUpdate(mangaMap: List<LibraryItem>, freshStart: Boolean = false) {
|
fun onNextLibraryUpdate(mangaMap: List<LibraryItem>, freshStart: Boolean = false) {
|
||||||
val view = view ?: return
|
view ?: return
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
if (mangaMap.isNotEmpty()) {
|
if (mangaMap.isNotEmpty()) {
|
||||||
empty_view?.hide()
|
empty_view?.hide()
|
||||||
@ -712,12 +633,6 @@ class LibraryController(
|
|||||||
} else recycler_layout.alpha = 1f
|
} else recycler_layout.alpha = 1f
|
||||||
if (justStarted && freshStart) {
|
if (justStarted && freshStart) {
|
||||||
scrollToHeader(activeCategory)
|
scrollToHeader(activeCategory)
|
||||||
if (!alwaysShowScroller) {
|
|
||||||
fast_scroller?.show(false)
|
|
||||||
view.post {
|
|
||||||
scrollAnim = fast_scroller?.hide(2000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
category_hopper_frame.visibleIf(!singleCategory)
|
category_hopper_frame.visibleIf(!singleCategory)
|
||||||
adapter.isLongPressDragEnabled = canDrag()
|
adapter.isLongPressDragEnabled = canDrag()
|
||||||
|
@ -67,6 +67,7 @@ class LibraryGestureDetector(private val controller: LibraryController) : Gestur
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
controller.hopperGravity = controller.preferences.hopperGravity().get()
|
||||||
result = true
|
result = true
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
@ -8,7 +8,6 @@ import android.text.SpannableString
|
|||||||
import android.text.style.ForegroundColorSpan
|
import android.text.style.ForegroundColorSpan
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
@ -17,7 +16,6 @@ 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 com.github.florent37.viewtooltip.ViewTooltip
|
import com.github.florent37.viewtooltip.ViewTooltip
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.SelectableAdapter
|
import eu.davidea.flexibleadapter.SelectableAdapter
|
||||||
@ -27,7 +25,6 @@ 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.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
|
||||||
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder
|
||||||
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
|
||||||
@ -42,8 +39,7 @@ import uy.kohesive.injekt.api.get
|
|||||||
|
|
||||||
class LibraryHeaderItem(
|
class LibraryHeaderItem(
|
||||||
private val categoryF: (Int) -> Category,
|
private val categoryF: (Int) -> Category,
|
||||||
private val catId: Int,
|
private val catId: Int
|
||||||
private val showFastScroll: Preference<Boolean>
|
|
||||||
) :
|
) :
|
||||||
AbstractHeaderItem<LibraryHeaderItem.Holder>() {
|
AbstractHeaderItem<LibraryHeaderItem.Holder>() {
|
||||||
|
|
||||||
@ -55,7 +51,7 @@ class LibraryHeaderItem(
|
|||||||
view: View,
|
view: View,
|
||||||
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>
|
adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>
|
||||||
): Holder {
|
): Holder {
|
||||||
return Holder(view, adapter as LibraryCategoryAdapter, showFastScroll.getOrDefault())
|
return Holder(view, adapter as LibraryCategoryAdapter)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun bindViewHolder(
|
override fun bindViewHolder(
|
||||||
@ -90,7 +86,7 @@ class LibraryHeaderItem(
|
|||||||
return -(category.id!!)
|
return -(category.id!!)
|
||||||
}
|
}
|
||||||
|
|
||||||
class Holder(val view: View, private val adapter: LibraryCategoryAdapter, padEnd: Boolean) :
|
class Holder(val view: View, private val adapter: LibraryCategoryAdapter) :
|
||||||
BaseFlexibleViewHolder(view, adapter, true) {
|
BaseFlexibleViewHolder(view, adapter, true) {
|
||||||
|
|
||||||
private val sectionText: TextView = view.findViewById(R.id.category_title)
|
private val sectionText: TextView = view.findViewById(R.id.category_title)
|
||||||
@ -101,9 +97,6 @@ class LibraryHeaderItem(
|
|||||||
private val catProgress: ProgressBar = view.findViewById(R.id.cat_progress)
|
private val catProgress: ProgressBar = view.findViewById(R.id.cat_progress)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sortText.updateLayoutParams<ViewGroup.MarginLayoutParams> {
|
|
||||||
marginEnd = (if (padEnd && adapter.recyclerView.paddingEnd == 0) 12 else 2).dpToPx
|
|
||||||
}
|
|
||||||
category_header_layout.setOnClickListener { toggleCategory() }
|
category_header_layout.setOnClickListener { toggleCategory() }
|
||||||
updateButton.setOnClickListener { addCategoryToUpdate() }
|
updateButton.setOnClickListener { addCategoryToUpdate() }
|
||||||
sectionText.setOnLongClickListener {
|
sectionText.setOnLongClickListener {
|
||||||
|
@ -37,9 +37,6 @@ class LibraryItem(
|
|||||||
var unreadType = 2
|
var unreadType = 2
|
||||||
var chapterCount = -1
|
var chapterCount = -1
|
||||||
|
|
||||||
private val showFastScroll: Boolean
|
|
||||||
get() = preferences.alwaysShowSeeker().getOrDefault()
|
|
||||||
|
|
||||||
private val uniformSize: Boolean
|
private val uniformSize: Boolean
|
||||||
get() = preferences.uniformGrid().getOrDefault()
|
get() = preferences.uniformGrid().getOrDefault()
|
||||||
|
|
||||||
@ -62,7 +59,7 @@ class LibraryItem(
|
|||||||
val libraryLayout = libraryLayout
|
val libraryLayout = libraryLayout
|
||||||
val isFixedSize = uniformSize
|
val isFixedSize = uniformSize
|
||||||
if (libraryLayout == 0 || manga.isBlank()) {
|
if (libraryLayout == 0 || manga.isBlank()) {
|
||||||
LibraryListHolder(view, adapter as LibraryCategoryAdapter, showFastScroll)
|
LibraryListHolder(view, adapter as LibraryCategoryAdapter)
|
||||||
} else {
|
} else {
|
||||||
view.apply {
|
view.apply {
|
||||||
val coverHeight = (parent.itemWidth / 3f * 4f).toInt()
|
val coverHeight = (parent.itemWidth / 3f * 4f).toInt()
|
||||||
@ -107,7 +104,7 @@ class LibraryItem(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
LibraryListHolder(view, adapter as LibraryCategoryAdapter, showFastScroll)
|
LibraryListHolder(view, adapter as LibraryCategoryAdapter)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,16 +29,9 @@ 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.
|
||||||
|
@ -118,11 +118,7 @@ class LibraryPresenter(
|
|||||||
private fun blankItem(id: Int = currentCategory): List<LibraryItem> {
|
private fun blankItem(id: Int = currentCategory): List<LibraryItem> {
|
||||||
return listOf(
|
return listOf(
|
||||||
LibraryItem(
|
LibraryItem(
|
||||||
LibraryManga.createBlank(id), LibraryHeaderItem(
|
LibraryManga.createBlank(id), LibraryHeaderItem({ getCategory(id) }, id)
|
||||||
{ getCategory(id) },
|
|
||||||
id,
|
|
||||||
preferences.alwaysShowSeeker()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -499,7 +495,6 @@ class LibraryPresenter(
|
|||||||
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
val categories = db.getCategories().executeAsBlocking().toMutableList()
|
||||||
val showCategories = !preferences.hideCategories().getOrDefault()
|
val showCategories = !preferences.hideCategories().getOrDefault()
|
||||||
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
var libraryManga = db.getLibraryMangas().executeAsBlocking()
|
||||||
val seekPref = preferences.alwaysShowSeeker()
|
|
||||||
val showAll = showAllCategories
|
val showAll = showAllCategories
|
||||||
if (!showCategories) libraryManga = libraryManga.distinctBy { it.id }
|
if (!showCategories) libraryManga = libraryManga.distinctBy { it.id }
|
||||||
val categoryAll = Category.createAll(
|
val categoryAll = Category.createAll(
|
||||||
@ -507,13 +502,13 @@ class LibraryPresenter(
|
|||||||
preferences.librarySortingMode().getOrDefault(),
|
preferences.librarySortingMode().getOrDefault(),
|
||||||
preferences.librarySortingAscending().getOrDefault()
|
preferences.librarySortingAscending().getOrDefault()
|
||||||
)
|
)
|
||||||
val catItemAll = LibraryHeaderItem({ categoryAll }, -1, seekPref)
|
val catItemAll = LibraryHeaderItem({ categoryAll }, -1)
|
||||||
val categorySet = mutableSetOf<Int>()
|
val categorySet = mutableSetOf<Int>()
|
||||||
val headerItems = (categories.mapNotNull { category ->
|
val headerItems = (categories.mapNotNull { category ->
|
||||||
val id = category.id
|
val id = category.id
|
||||||
if (id == null) null
|
if (id == null) null
|
||||||
else id to LibraryHeaderItem({ getCategory(id) }, id, seekPref)
|
else id to LibraryHeaderItem({ getCategory(id) }, id)
|
||||||
} + (-1 to catItemAll) + (0 to LibraryHeaderItem({ getCategory(0) }, 0, seekPref))).toMap()
|
} + (-1 to catItemAll) + (0 to LibraryHeaderItem({ getCategory(0) }, 0))).toMap()
|
||||||
val items = libraryManga.mapNotNull {
|
val items = libraryManga.mapNotNull {
|
||||||
val headerItem = (if (!showCategories) catItemAll
|
val headerItem = (if (!showCategories) catItemAll
|
||||||
else headerItems[it.category]) ?: return@mapNotNull null
|
else headerItems[it.category]) ?: return@mapNotNull null
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package eu.kanade.tachiyomi.ui.library
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.view.MotionEvent
|
||||||
|
import eu.davidea.fastscroller.FastScroller
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.util.system.dpToPxEnd
|
||||||
|
|
||||||
|
class MaterialFastScroll @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||||
|
FastScroller(context, attrs) {
|
||||||
|
|
||||||
|
init {
|
||||||
|
setViewsToUse(
|
||||||
|
R.layout.material_fastscroll, R.id.fast_scroller_bubble, R.id.fast_scroller_handle
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
|
if (isHidden) return false
|
||||||
|
return super.onTouchEvent(event)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setBubbleAndHandlePosition(y: Float) {
|
||||||
|
super.setBubbleAndHandlePosition(y)
|
||||||
|
bubble.y = handle.y - bubble.height / 2f + handle.height / 2f
|
||||||
|
bubble.translationX = (-45f).dpToPxEnd
|
||||||
|
}
|
||||||
|
}
|
@ -55,7 +55,6 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att
|
|||||||
val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
|
val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
|
||||||
val count = max(1, (dpWidth / columnWidth).roundToInt())
|
val count = max(1, (dpWidth / columnWidth).roundToInt())
|
||||||
spanCount = count
|
spanCount = count
|
||||||
// Timber.d("Dp width: $dpWidth - RSpan: $spanCount")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
9
app/src/main/res/drawable/bubble_drawable.xml
Normal file
9
app/src/main/res/drawable/bubble_drawable.xml
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="rectangle">
|
||||||
|
<corners android:radius="38dp"/>
|
||||||
|
<solid android:color="?colorPrimaryVariant" />
|
||||||
|
<size
|
||||||
|
android:width="30dp"
|
||||||
|
android:height="30dp"/>
|
||||||
|
</shape>
|
17
app/src/main/res/drawable/thumb_drawable.xml
Normal file
17
app/src/main/res/drawable/thumb_drawable.xml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item android:state_selected="true">
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:radius="8dp"/>
|
||||||
|
<solid android:color="@color/colorAccent"/>
|
||||||
|
<size android:width="6dp" android:height="54dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<shape android:shape="rectangle">
|
||||||
|
<corners android:radius="8dp"/>
|
||||||
|
<solid android:color="@color/fast_scroller_handle_idle"/>
|
||||||
|
<size android:width="6dp" android:height="54dp"/>
|
||||||
|
</shape>
|
||||||
|
</item>
|
||||||
|
</selector>
|
@ -173,14 +173,6 @@
|
|||||||
android:layout_marginEnd="12dp"
|
android:layout_marginEnd="12dp"
|
||||||
android:text="@string/download_badge" />
|
android:text="@string/download_badge" />
|
||||||
|
|
||||||
<com.google.android.material.checkbox.MaterialCheckBox
|
|
||||||
android:id="@+id/autohide_seeker"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="12dp"
|
|
||||||
android:layout_marginEnd="12dp"
|
|
||||||
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"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<eu.kanade.tachiyomi.widget.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
<eu.kanade.tachiyomi.widget.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
style="@style/Theme.Widget.GridView.Catalogue"
|
|
||||||
android:id="@+id/recycler"
|
android:id="@+id/recycler"
|
||||||
|
style="@style/Theme.Widget.GridView.Catalogue"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:columnWidth="140dp"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:background="@drawable/bottom_sheet_rounded_background"
|
android:background="@drawable/bottom_sheet_rounded_background"
|
||||||
tools:listitem="@layout/manga_grid_item"/>
|
android:clipToPadding="false"
|
||||||
|
android:columnWidth="140dp"
|
||||||
|
tools:listitem="@layout/manga_grid_item" />
|
||||||
|
@ -51,6 +51,15 @@
|
|||||||
|
|
||||||
<include layout="@layout/library_grid_recycler" />
|
<include layout="@layout/library_grid_recycler" />
|
||||||
|
|
||||||
|
<eu.kanade.tachiyomi.ui.library.MaterialFastScroll
|
||||||
|
android:id="@+id/fast_scroller"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
app:fastScrollerAutoHideEnabled="true"
|
||||||
|
app:fastScrollerAutoHideDelayInMillis="1000"
|
||||||
|
app:fastScrollerBubbleEnabled="true"
|
||||||
|
app:fastScrollerIgnoreTouchesOutsideHandle="true"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/recycler_cover"
|
android:id="@+id/recycler_cover"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -61,42 +70,6 @@
|
|||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<com.reddit.indicatorfastscroll.FastScrollerView
|
|
||||||
android:id="@+id/fast_scroller"
|
|
||||||
android:layout_width="25dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="end"
|
|
||||||
android:background="@drawable/fast_scroll_background"
|
|
||||||
android:elevation="10dp"
|
|
||||||
android:paddingStart="3dp"
|
|
||||||
android:paddingTop="8dp"
|
|
||||||
android:paddingEnd="0dp"
|
|
||||||
android:paddingBottom="8dp"
|
|
||||||
android:textColor="?android:attr/textColorPrimaryInverse"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<com.google.android.material.textview.MaterialTextView
|
|
||||||
android:id="@+id/text_view_m"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="50dp"
|
|
||||||
android:alpha="0"
|
|
||||||
android:background="@drawable/round_textview_background"
|
|
||||||
android:padding="10dp"
|
|
||||||
android:textColor="@android:color/white"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/fast_scroller"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/fast_scroller"
|
|
||||||
tools:alpha="1"
|
|
||||||
tools:text="Category" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
<eu.kanade.tachiyomi.widget.EmptyView
|
<eu.kanade.tachiyomi.widget.EmptyView
|
||||||
android:id="@+id/empty_view"
|
android:id="@+id/empty_view"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -114,11 +87,33 @@
|
|||||||
app:layout_anchor="@id/filter_bottom_sheet"
|
app:layout_anchor="@id/filter_bottom_sheet"
|
||||||
app:layout_anchorGravity="top" />
|
app:layout_anchorGravity="top" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:elevation="10dp"
|
||||||
|
android:id="@+id/jumper_category_text"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_anchor="@id/category_hopper_frame"
|
||||||
|
android:background="@drawable/bubble_drawable"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:layout_marginBottom="12dp"
|
||||||
|
android:layout_gravity="start|center"
|
||||||
|
app:layout_anchorGravity="start|center"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:alpha="0.0"
|
||||||
|
android:textColor="?actionBarTintColor"
|
||||||
|
android:textSize="15sp"
|
||||||
|
tools:alpha="1"
|
||||||
|
tools:text="Category and a long one"/>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:id="@+id/category_hopper_frame"
|
android:id="@+id/category_hopper_frame"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="top|center"
|
android:layout_gravity="top|center"
|
||||||
|
android:elevation="11dp"
|
||||||
app:layout_anchor="@id/filter_bottom_sheet"
|
app:layout_anchor="@id/filter_bottom_sheet"
|
||||||
app:layout_anchorGravity="top|center">
|
app:layout_anchorGravity="top|center">
|
||||||
|
|
||||||
|
52
app/src/main/res/layout/material_fastscroll.xml
Normal file
52
app/src/main/res/layout/material_fastscroll.xml
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<merge xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/fast_scroller_bar"
|
||||||
|
android:layout_width="7dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end"
|
||||||
|
android:background="@android:color/transparent"/>
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end">
|
||||||
|
|
||||||
|
<!-- No margin, use padding at the handle -->
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:elevation="10dp"
|
||||||
|
android:id="@+id/fast_scroller_bubble"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="end|center_vertical"
|
||||||
|
android:layout_toStartOf="@+id/fast_scroller_handle"
|
||||||
|
android:background="@drawable/bubble_drawable"
|
||||||
|
android:gravity="center"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp"
|
||||||
|
android:paddingTop="8dp"
|
||||||
|
android:paddingBottom="8dp"
|
||||||
|
android:textColor="?actionBarTintColor"
|
||||||
|
android:textSize="15sp"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:text="A"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
|
<!-- Padding is here to have better grab -->
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/fast_scroller_handle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentEnd="true"
|
||||||
|
android:contentDescription="@null"
|
||||||
|
android:paddingStart="6dp"
|
||||||
|
android:paddingEnd="4dp"
|
||||||
|
android:src="@drawable/thumb_drawable"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
|
</merge>
|
@ -4,7 +4,7 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:layout_marginStart="20dp"
|
||||||
android:layout_marginTop="20dp"
|
android:layout_marginTop="10dp"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginEnd="20dp"
|
||||||
android:layout_marginBottom="10dp"
|
android:layout_marginBottom="10dp"
|
||||||
app:cardCornerRadius="25dp"
|
app:cardCornerRadius="25dp"
|
||||||
|
@ -133,7 +133,6 @@
|
|||||||
<string name="start_with_filters_hidden">Start with filters hidden</string>
|
<string name="start_with_filters_hidden">Start with filters hidden</string>
|
||||||
<string name="download_badge">Download badges</string>
|
<string name="download_badge">Download badges</string>
|
||||||
<string name="hide_start_reading_button">Hide start reading button</string>
|
<string name="hide_start_reading_button">Hide start reading button</string>
|
||||||
<string name="always_show_library_fast_scroll">Always show library fast scroll</string>
|
|
||||||
<string name="unread_badges">Unread badges</string>
|
<string name="unread_badges">Unread badges</string>
|
||||||
<string name="uniform_covers">Uniform covers</string>
|
<string name="uniform_covers">Uniform covers</string>
|
||||||
<string name="x_small">XS</string>
|
<string name="x_small">XS</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user