Starting work on viewbinding

This commit is contained in:
Jays2Kings 2021-03-28 21:17:20 -04:00
parent 8c9fbc9568
commit ccb7dbb714
20 changed files with 111 additions and 91 deletions

View File

@ -58,6 +58,10 @@ android {
} }
} }
buildFeatures {
viewBinding = true
}
flavorDimensions("default") flavorDimensions("default")
productFlavors { productFlavors {

View File

@ -6,6 +6,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.viewbinding.ViewBinding
import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.ControllerChangeHandler import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
@ -14,10 +15,12 @@ import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.* import kotlinx.android.synthetic.*
import timber.log.Timber import timber.log.Timber
abstract class BaseController(bundle: Bundle? = null) : abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
RestoreViewOnCreateController(bundle), RestoreViewOnCreateController(bundle),
LayoutContainer { LayoutContainer {
lateinit var binding: VB
init { init {
addLifecycleListener( addLifecycleListener(
object : LifecycleListener() { object : LifecycleListener() {
@ -78,7 +81,7 @@ abstract class BaseController(bundle: Bundle? = null) :
fun setTitle() { fun setTitle() {
var parentController = parentController var parentController = parentController
while (parentController != null) { while (parentController != null) {
if (parentController is BaseController && parentController.getTitle() != null) { if (parentController is BaseController<*> && parentController.getTitle() != null) {
return return
} }
parentController = parentController.parentController parentController = parentController.parentController

View File

@ -1,14 +1,15 @@
package eu.kanade.tachiyomi.ui.base.controller package eu.kanade.tachiyomi.ui.base.controller
import android.os.Bundle import android.os.Bundle
import androidx.viewbinding.ViewBinding
import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorDelegate import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorDelegate
import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorLifecycleListener import eu.kanade.tachiyomi.ui.base.presenter.NucleusConductorLifecycleListener
import nucleus.factory.PresenterFactory import nucleus.factory.PresenterFactory
import nucleus.presenter.Presenter import nucleus.presenter.Presenter
@Suppress("LeakingThis") @Suppress("LeakingThis")
abstract class NucleusController<P : Presenter<*>>(val bundle: Bundle? = null) : abstract class NucleusController<VB : ViewBinding, P : Presenter<*>>(val bundle: Bundle? = null) :
RxController(bundle), RxController<VB>(bundle),
PresenterFactory<P> { PresenterFactory<P> {
private val delegate = NucleusConductorDelegate(this) private val delegate = NucleusConductorDelegate(this)

View File

@ -3,11 +3,12 @@ package eu.kanade.tachiyomi.ui.base.controller
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import androidx.annotation.CallSuper import androidx.annotation.CallSuper
import androidx.viewbinding.ViewBinding
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.subscriptions.CompositeSubscription import rx.subscriptions.CompositeSubscription
abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) { abstract class RxController<VB : ViewBinding>(bundle: Bundle? = null) : BaseController<VB>(bundle) {
var untilDetachSubscriptions = CompositeSubscription() var untilDetachSubscriptions = CompositeSubscription()
private set private set

View File

@ -11,6 +11,7 @@ import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.CategoriesControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.category.CategoryPresenter.Companion.CREATE_CATEGORY_ORDER import eu.kanade.tachiyomi.ui.category.CategoryPresenter.Companion.CREATE_CATEGORY_ORDER
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
@ -23,7 +24,7 @@ import kotlinx.android.synthetic.main.categories_controller.*
* Controller to manage the categories for the users' library. * Controller to manage the categories for the users' library.
*/ */
class CategoryController(bundle: Bundle? = null) : class CategoryController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<CategoriesControllerBinding>(bundle),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemMoveListener, FlexibleAdapter.OnItemMoveListener,
CategoryAdapter.CategoryItemListener { CategoryAdapter.CategoryItemListener {

View File

@ -34,6 +34,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore import eu.kanade.tachiyomi.data.preference.SharedPreferencesDataStore
import eu.kanade.tachiyomi.data.preference.minusAssign import eu.kanade.tachiyomi.data.preference.minusAssign
import eu.kanade.tachiyomi.data.preference.plusAssign import eu.kanade.tachiyomi.data.preference.plusAssign
import eu.kanade.tachiyomi.databinding.ExtensionDetailControllerBinding
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.getPreferenceKey import eu.kanade.tachiyomi.source.getPreferenceKey
@ -55,7 +56,7 @@ import uy.kohesive.injekt.api.get
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
class ExtensionDetailsController(bundle: Bundle? = null) : class ExtensionDetailsController(bundle: Bundle? = null) :
NucleusController<ExtensionDetailsPresenter>(bundle), NucleusController<ExtensionDetailControllerBinding, ExtensionDetailsPresenter>(bundle),
PreferenceManager.OnDisplayPreferenceDialogListener, PreferenceManager.OnDisplayPreferenceDialogListener,
DialogPreference.TargetFragment { DialogPreference.TargetFragment {

View File

@ -52,6 +52,7 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
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.databinding.LibraryListControllerBinding
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet import eu.kanade.tachiyomi.ui.base.MaterialMenuSheet
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
@ -99,8 +100,6 @@ import kotlinx.android.synthetic.main.filter_bottom_sheet.*
import kotlinx.android.synthetic.main.filter_bottom_sheet.view.* import kotlinx.android.synthetic.main.filter_bottom_sheet.view.*
import kotlinx.android.synthetic.main.library_grid_recycler.* import kotlinx.android.synthetic.main.library_grid_recycler.*
import kotlinx.android.synthetic.main.library_grid_recycler.recycler import kotlinx.android.synthetic.main.library_grid_recycler.recycler
import kotlinx.android.synthetic.main.library_list_controller.*
import kotlinx.android.synthetic.main.library_list_controller.shadow2
import kotlinx.android.synthetic.main.main_activity.* import kotlinx.android.synthetic.main.main_activity.*
import kotlinx.android.synthetic.main.rounded_category_hopper.* import kotlinx.android.synthetic.main.rounded_category_hopper.*
import kotlinx.android.synthetic.main.source_controller.* import kotlinx.android.synthetic.main.source_controller.*
@ -116,7 +115,7 @@ import kotlin.random.nextInt
class LibraryController( class LibraryController(
bundle: Bundle? = null, bundle: Bundle? = null,
val preferences: PreferencesHelper = Injekt.get() val preferences: PreferencesHelper = Injekt.get()
) : BaseController(bundle), ) : BaseController<LibraryListControllerBinding>(bundle),
ActionMode.Callback, ActionMode.Callback,
ChangeMangaCategoriesDialog.Listener, ChangeMangaCategoriesDialog.Listener,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
@ -182,10 +181,10 @@ class LibraryController(
private var hasExpanded = false private var hasExpanded = false
var hopperGravity: Int = preferences.hopperGravity().get() var hopperGravity: Int = preferences.hopperGravity().get()
@SuppressLint("RtlHardcoded")
set(value) { set(value) {
field = value field = value
if (category_hopper_frame == null) return binding.jumperCategoryText.updateLayoutParams<CoordinatorLayout.LayoutParams> {
jumper_category_text.updateLayoutParams<CoordinatorLayout.LayoutParams> {
anchorGravity = when (value) { anchorGravity = when (value) {
0 -> Gravity.RIGHT or Gravity.CENTER_VERTICAL 0 -> Gravity.RIGHT or Gravity.CENTER_VERTICAL
2 -> Gravity.LEFT or Gravity.CENTER_VERTICAL 2 -> Gravity.LEFT or Gravity.CENTER_VERTICAL
@ -206,17 +205,17 @@ class LibraryController(
private var hopperOffset = 0f private var hopperOffset = 0f
override fun getTitle(): String? { override fun getTitle(): String? {
return if (!showCategoryInTitle || header_title.text.isNullOrBlank() || recycler_cover?.isClickable == true) { return if (!showCategoryInTitle || binding.headerTitle.text.isNullOrBlank() || binding.recyclerCover.isClickable) {
view?.context?.getString(R.string.library) view?.context?.getString(R.string.library)
} else { } else {
header_title.text.toString() binding.headerTitle.text.toString()
} }
} }
private var scrollListener = object : RecyclerView.OnScrollListener() { private var scrollListener = object : RecyclerView.OnScrollListener() {
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
super.onScrolled(recyclerView, dx, dy) super.onScrolled(recyclerView, dx, dy)
val recyclerCover = recycler_cover ?: return val recyclerCover = binding.recyclerCover
if (!recyclerCover.isClickable && isAnimatingHopper != true) { if (!recyclerCover.isClickable && isAnimatingHopper != true) {
if (preferences.autohideHopper().get()) { if (preferences.autohideHopper().get()) {
hopperOffset += dy hopperOffset += dy
@ -251,10 +250,9 @@ class LibraryController(
override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
super.onScrollStateChanged(recyclerView, newState) super.onScrollStateChanged(recyclerView, newState)
recycler_cover ?: return
when (newState) { when (newState) {
RecyclerView.SCROLL_STATE_DRAGGING -> { RecyclerView.SCROLL_STATE_DRAGGING -> {
fast_scroller.showScrollbar() binding.fastScroller.showScrollbar()
} }
RecyclerView.SCROLL_STATE_IDLE -> { RecyclerView.SCROLL_STATE_IDLE -> {
updateHopperPosition() updateHopperPosition()
@ -288,7 +286,7 @@ class LibraryController(
) )
filter_bottom_sheet.sheetBehavior?.peekHeight = 60.dpToPx + padding filter_bottom_sheet.sheetBehavior?.peekHeight = 60.dpToPx + padding
updateHopperY() updateHopperY()
fast_scroller.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
bottomMargin = -pad.toInt() bottomMargin = -pad.toInt()
} }
} }
@ -325,40 +323,39 @@ class LibraryController(
fun saveActiveCategory(category: Category) { fun saveActiveCategory(category: Category) {
activeCategory = category.order activeCategory = category.order
val headerItem = getHeader() ?: return val headerItem = getHeader() ?: return
header_title.text = headerItem.category.name binding.headerTitle.text = headerItem.category.name
setActiveCategory() setActiveCategory()
} }
private fun setActiveCategory() { private fun setActiveCategory() {
category_recycler ?: return
val currentCategory = presenter.categories.indexOfFirst { val currentCategory = presenter.categories.indexOfFirst {
if (presenter.showAllCategories) it.order == activeCategory else presenter.currentCategory == it.id if (presenter.showAllCategories) it.order == activeCategory else presenter.currentCategory == it.id
} }
if (currentCategory > -1) { if (currentCategory > -1) {
category_recycler.setCategories(currentCategory) binding.categoryRecycler.setCategories(currentCategory)
header_title.text = presenter.categories[currentCategory].name binding.headerTitle.text = presenter.categories[currentCategory].name
setTitle() setTitle()
} }
} }
fun showMiniBar() { fun showMiniBar() {
header_title.visibleIf(showCategoryInTitle) binding.headerTitle.visibleIf(showCategoryInTitle)
setTitle() setTitle()
} }
fun showCategoryText(name: String) { fun showCategoryText(name: String) {
textAnim?.cancel() textAnim?.cancel()
textAnim = jumper_category_text.animate().alpha(0f).setDuration(250L).setStartDelay(2000) textAnim = binding.jumperCategoryText.animate().alpha(0f).setDuration(250L).setStartDelay(2000)
textAnim?.start() textAnim?.start()
jumper_category_text.alpha = 1f binding.jumperCategoryText.alpha = 1f
jumper_category_text.text = name binding.jumperCategoryText.text = name
} }
fun isAtTop(): Boolean { fun isAtTop(): Boolean {
return if (presenter.showAllCategories) { return if (presenter.showAllCategories) {
!recycler.canScrollVertically(-1) !recycler.canScrollVertically(-1)
} else { } else {
getVisibleHeader()?.category?.order == presenter.categories.minBy { it.order }?.order getVisibleHeader()?.category?.order == presenter.categories.minOfOrNull { it.order }
} }
} }
@ -366,7 +363,7 @@ class LibraryController(
return if (presenter.showAllCategories) { return if (presenter.showAllCategories) {
!recycler.canScrollVertically(1) !recycler.canScrollVertically(1)
} else { } else {
getVisibleHeader()?.category?.order == presenter.categories.maxBy { it.order }?.order getVisibleHeader()?.category?.order == presenter.categories.maxOfOrNull { it.order }
} }
} }
@ -415,20 +412,20 @@ class LibraryController(
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)
recycler.adapter = adapter recycler.adapter = adapter
adapter.fastScroller = fast_scroller adapter.fastScroller = binding.fastScroller
recycler.addOnScrollListener(scrollListener) recycler.addOnScrollListener(scrollListener)
swipe_refresh.setStyle() binding.swipeRefresh.setStyle()
recycler_cover.setOnClickListener { binding.recyclerCover.setOnClickListener {
showCategories(false) showCategories(false)
} }
category_recycler.onCategoryClicked = { binding.categoryRecycler.onCategoryClicked = {
recycler.itemAnimator = null recycler.itemAnimator = null
scrollToHeader(it) scrollToHeader(it)
showCategories(show = false) showCategories(show = false)
} }
category_recycler.onShowAllClicked = { isChecked -> binding.categoryRecycler.onShowAllClicked = { isChecked ->
preferences.showAllCategories().set(isChecked) preferences.showAllCategories().set(isChecked)
presenter.getLibrary() presenter.getLibrary()
} }
@ -438,26 +435,26 @@ class LibraryController(
elevateAppBar = elevateAppBar =
scrollViewWith( scrollViewWith(
recycler, recycler,
swipeRefreshLayout = swipe_refresh, swipeRefreshLayout = binding.swipeRefresh,
afterInsets = { insets -> afterInsets = { insets ->
category_recycler?.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.categoryRecycler.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = recycler?.paddingTop ?: 0 topMargin = recycler?.paddingTop ?: 0
} }
fast_scroller?.updateLayoutParams<ViewGroup.MarginLayoutParams> { binding.fastScroller.updateLayoutParams<ViewGroup.MarginLayoutParams> {
topMargin = recycler?.paddingTop ?: 0 topMargin = recycler?.paddingTop ?: 0
} }
header_title?.updatePaddingRelative(top = insets.systemWindowInsetTop + 2.dpToPx) binding.headerTitle.updatePaddingRelative(top = insets.systemWindowInsetTop + 2.dpToPx)
}, },
onLeavingController = { onLeavingController = {
header_title?.gone() binding.headerTitle.gone()
}, },
onBottomNavUpdate = { onBottomNavUpdate = {
updateFilterSheetY() updateFilterSheetY()
} }
) )
swipe_refresh.setOnRefreshListener { binding.swipeRefresh.setOnRefreshListener {
swipe_refresh.isRefreshing = false binding.swipeRefresh.isRefreshing = false
if (!LibraryUpdateService.isRunning()) { if (!LibraryUpdateService.isRunning()) {
when { when {
!presenter.showAllCategories && presenter.groupType == BY_DEFAULT -> { !presenter.showAllCategories && presenter.groupType == BY_DEFAULT -> {
@ -508,7 +505,7 @@ class LibraryController(
if (presenter.libraryItems.isNotEmpty()) { if (presenter.libraryItems.isNotEmpty()) {
presenter.restoreLibrary() presenter.restoreLibrary()
} else { } else {
recycler_layout.alpha = 0f binding.recyclerLayout.alpha = 0f
presenter.getLibrary() presenter.getLibrary()
} }
} }
@ -560,7 +557,7 @@ class LibraryController(
@SuppressLint("RtlHardcoded", "ClickableViewAccessibility") @SuppressLint("RtlHardcoded", "ClickableViewAccessibility")
private fun setUpHopper() { private fun setUpHopper() {
category_hopper_frame.gone() binding.categoryHopperFrame.gone()
down_category.setOnClickListener { down_category.setOnClickListener {
jumpToNextCategory(true) jumpToNextCategory(true)
} }
@ -602,7 +599,7 @@ class LibraryController(
preferences.hopperGravity().get() preferences.hopperGravity().get()
} }
hideHopper(preferences.hideHopper().get()) hideHopper(preferences.hideHopper().get())
category_hopper_frame.updateLayoutParams<CoordinatorLayout.LayoutParams> { binding.categoryHopperFrame.updateLayoutParams<CoordinatorLayout.LayoutParams> {
gravity = Gravity.TOP or when (gravityPref) { gravity = Gravity.TOP or when (gravityPref) {
0 -> Gravity.LEFT 0 -> Gravity.LEFT
2 -> Gravity.RIGHT 2 -> Gravity.RIGHT
@ -620,7 +617,7 @@ class LibraryController(
if (event?.action == MotionEvent.ACTION_UP) { if (event?.action == MotionEvent.ACTION_UP) {
val result = gestureDetector.onTouchEvent(event) val result = gestureDetector.onTouchEvent(event)
if (!result) { if (!result) {
category_hopper_frame.animate().setDuration(150L).translationX(0f).start() binding.categoryHopperFrame.animate().setDuration(150L).translationX(0f).start()
} }
result result
} else { } else {
@ -640,14 +637,14 @@ class LibraryController(
if (!preferences.autohideHopper().get()) { if (!preferences.autohideHopper().get()) {
listOfYs.add(view.height - (insetBottom).toFloat()) listOfYs.add(view.height - (insetBottom).toFloat())
} }
category_hopper_frame.y = -category_hopper_frame.height + binding.categoryHopperFrame.y = -binding.categoryHopperFrame.height +
(listOfYs.minOrNull() ?: filter_bottom_sheet.y) + (listOfYs.minOrNull() ?: filter_bottom_sheet.y) +
hopperOffset + hopperOffset +
recycler.translationY recycler.translationY
if (view.height - insetBottom < category_hopper_frame.y) { if (view.height - insetBottom < binding.categoryHopperFrame.y) {
jumper_category_text.translationY = -(category_hopper_frame.y - (view.height - insetBottom)) + recycler.translationY binding.jumperCategoryText.translationY = -(binding.categoryHopperFrame.y - (view.height - insetBottom)) + recycler.translationY
} else { } else {
jumper_category_text.translationY = recycler.translationY binding.jumperCategoryText.translationY = recycler.translationY
} }
} }
@ -656,8 +653,8 @@ class LibraryController(
} }
fun hideHopper(hide: Boolean) { fun hideHopper(hide: Boolean) {
category_hopper_frame.visibleIf(!hide) binding.categoryHopperFrame.visibleIf(!hide)
jumper_category_text.visibleIf(!hide) binding.jumperCategoryText.visibleIf(!hide)
} }
private fun jumpToNextCategory(next: Boolean) { private fun jumpToNextCategory(next: Boolean) {
@ -731,12 +728,13 @@ class LibraryController(
} }
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) binding = LibraryListControllerBinding.inflate(inflater)
return binding.root
} }
private fun anchorView(): View? { private fun anchorView(): View? {
return if (category_hopper_frame.isVisible()) { return if (binding.categoryHopperFrame.isVisible()) {
category_hopper_frame binding.categoryHopperFrame
} else { } else {
filter_bottom_sheet filter_bottom_sheet
} }
@ -787,8 +785,8 @@ class LibraryController(
presenter.getLibrary() presenter.getLibrary()
DownloadService.callListeners() DownloadService.callListeners()
LibraryUpdateService.setListener(this) LibraryUpdateService.setListener(this)
recycler_cover.isClickable = false binding.recyclerCover.isClickable = false
recycler_cover.isFocusable = false binding.recyclerCover.isFocusable = false
showDropdown() showDropdown()
} else { } else {
updateFilterSheetY() updateFilterSheetY()
@ -837,9 +835,9 @@ class LibraryController(
view ?: return view ?: return
destroyActionModeIfNeeded() destroyActionModeIfNeeded()
if (mangaMap.isNotEmpty()) { if (mangaMap.isNotEmpty()) {
empty_view?.hide() binding.emptyView.hide()
} else { } else {
empty_view?.show( binding.emptyView.show(
R.drawable.ic_heart_off_24dp, R.drawable.ic_heart_off_24dp,
if (filter_bottom_sheet.hasActiveFilters()) R.string.no_matches_for_filters if (filter_bottom_sheet.hasActiveFilters()) R.string.no_matches_for_filters
else R.string.library_is_empty_add_from_browse else R.string.library_is_empty_add_from_browse
@ -853,12 +851,12 @@ class LibraryController(
} }
singleCategory = presenter.categories.size <= 1 singleCategory = presenter.categories.size <= 1
showDropdown() showDropdown()
progress.gone() binding.progress.gone()
if (!freshStart) { if (!freshStart) {
justStarted = false justStarted = false
if (recycler_layout.alpha == 0f) recycler_layout.animate().alpha(1f).setDuration(500) if (binding.recyclerLayout.alpha == 0f) binding.recyclerLayout.animate().alpha(1f).setDuration(500)
.start() .start()
} else recycler_layout.alpha = 1f } else binding.recyclerLayout.alpha = 1f
if (justStarted && freshStart) { if (justStarted && freshStart) {
scrollToHeader(activeCategory) scrollToHeader(activeCategory)
} }
@ -867,20 +865,20 @@ class LibraryController(
setActiveCategory() setActiveCategory()
} }
category_hopper_frame.visibleIf(!singleCategory && !preferences.hideHopper().get()) binding.categoryHopperFrame.visibleIf(!singleCategory && !preferences.hideHopper().get())
filter_bottom_sheet.updateButtons( filter_bottom_sheet.updateButtons(
showExpand = !singleCategory && presenter.showAllCategories, showExpand = !singleCategory && presenter.showAllCategories,
groupType = presenter.groupType groupType = presenter.groupType
) )
adapter.isLongPressDragEnabled = canDrag() adapter.isLongPressDragEnabled = canDrag()
category_recycler.setCategories(presenter.categories) binding.categoryRecycler.setCategories(presenter.categories)
filter_bottom_sheet.setExpandText(preferences.collapsedCategories().getOrDefault().isNotEmpty()) filter_bottom_sheet.setExpandText(preferences.collapsedCategories().getOrDefault().isNotEmpty())
if (shouldScrollToTop) { if (shouldScrollToTop) {
recycler.scrollToPosition(0) recycler.scrollToPosition(0)
shouldScrollToTop = false shouldScrollToTop = false
} }
if (onRoot) { if (onRoot) {
listOf(activity?.toolbar, header_title).forEach { listOf(activity?.toolbar, binding.headerTitle).forEach {
it?.setOnClickListener { it?.setOnClickListener {
val recycler = recycler ?: return@setOnClickListener val recycler = recycler ?: return@setOnClickListener
if (singleCategory) { if (singleCategory) {
@ -923,7 +921,7 @@ class LibraryController(
animatorSet.startDelay = 1250 animatorSet.startDelay = 1250
animatorSet.addListener( animatorSet.addListener(
EndAnimatorListener { EndAnimatorListener {
category_hopper_frame?.translationX = 0f binding.categoryHopperFrame.translationX = 0f
isAnimatingHopper = false isAnimatingHopper = false
this.animatorSet = null this.animatorSet = null
} }
@ -932,14 +930,14 @@ class LibraryController(
} }
private fun slideAnimation(from: Float, to: Float, duration: Long = 400): ObjectAnimator { private fun slideAnimation(from: Float, to: Float, duration: Long = 400): ObjectAnimator {
return ObjectAnimator.ofFloat(category_hopper_frame, View.TRANSLATION_X, from, to) return ObjectAnimator.ofFloat(binding.categoryHopperFrame, View.TRANSLATION_X, from, to)
.setDuration(duration) .setDuration(duration)
} }
private fun showCategories(show: Boolean) { private fun showCategories(show: Boolean) {
recycler_cover.isClickable = show binding.recyclerCover.isClickable = show
recycler_cover.isFocusable = show binding.recyclerCover.isFocusable = show
val full = category_recycler.height.toFloat() + recycler.paddingTop val full = binding.categoryRecycler.height.toFloat() + recycler.paddingTop
val translateY = if (show) full else 0f val translateY = if (show) full else 0f
recycler.animate().translationY(translateY).apply { recycler.animate().translationY(translateY).apply {
setUpdateListener { setUpdateListener {
@ -947,16 +945,16 @@ class LibraryController(
updateHopperY() updateHopperY()
} }
}.start() }.start()
recycler_shadow.animate().translationY(translateY - 8.dpToPx).start() binding.recyclerShadow.animate().translationY(translateY - 8.dpToPx).start()
recycler_cover.animate().translationY(translateY).start() binding.recyclerCover.animate().translationY(translateY).start()
recycler_cover.animate().alpha(if (show) 0.75f else 0f).start() binding.recyclerCover.animate().alpha(if (show) 0.75f else 0f).start()
recycler.suppressLayout(show) recycler.suppressLayout(show)
activity?.toolbar?.showDropdown(!show) activity?.toolbar?.showDropdown(!show)
swipe_refresh.isEnabled = !show binding.swipeRefresh.isEnabled = !show
setTitle() setTitle()
if (show) { if (show) {
category_recycler.scrollToCategory(activeCategory) binding.categoryRecycler.scrollToCategory(activeCategory)
fast_scroller?.hideScrollbar() binding.fastScroller.hideScrollbar()
activity?.appbar?.y = 0f activity?.appbar?.y = 0f
elevateAppBar(false) elevateAppBar(false)
filter_bottom_sheet?.sheetBehavior?.hide() filter_bottom_sheet?.sheetBehavior?.hide()
@ -1178,7 +1176,7 @@ class LibraryController(
override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) { override fun onActionStateChanged(viewHolder: RecyclerView.ViewHolder?, actionState: Int) {
val position = viewHolder?.bindingAdapterPosition ?: return val position = viewHolder?.bindingAdapterPosition ?: return
swipe_refresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_DRAG binding.swipeRefresh.isEnabled = actionState != ItemTouchHelper.ACTION_STATE_DRAG
if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) { if (actionState == ItemTouchHelper.ACTION_STATE_DRAG) {
if (lastItemPosition != null && if (lastItemPosition != null &&
position != lastItemPosition && position != lastItemPosition &&
@ -1290,8 +1288,8 @@ class LibraryController(
} }
} }
override fun updateCategory(position: Int): Boolean { override fun updateCategory(catId: Int): Boolean {
val category = (adapter.getItem(position) as? LibraryHeaderItem)?.category ?: return false val category = (adapter.getItem(catId) as? LibraryHeaderItem)?.category ?: return false
val inQueue = LibraryUpdateService.categoryInQueue(category.id) val inQueue = LibraryUpdateService.categoryInQueue(category.id)
snack?.dismiss() snack?.dismiss()
snack = view?.snack( snack = view?.snack(
@ -1382,7 +1380,7 @@ class LibraryController(
override fun sheetIsExpanded(): Boolean = false override fun sheetIsExpanded(): Boolean = false
override fun handleSheetBack(): Boolean { override fun handleSheetBack(): Boolean {
if (recycler_cover.isClickable) { if (binding.recyclerCover.isClickable) {
showCategories(false) showCategories(false)
return true return true
} }

View File

@ -297,7 +297,7 @@ open class MainActivity : BaseActivity(), DownloadServiceListener {
syncActivityViewWithController(router.backstack.lastOrNull()?.controller()) syncActivityViewWithController(router.backstack.lastOrNull()?.controller())
toolbar.navigationIcon = if (router.backstackSize > 1) drawerArrow else searchDrawable toolbar.navigationIcon = if (router.backstackSize > 1) drawerArrow else searchDrawable
(router.backstack.lastOrNull()?.controller() as? BaseController)?.setTitle() (router.backstack.lastOrNull()?.controller() as? BaseController<*>)?.setTitle()
(router.backstack.lastOrNull()?.controller() as? SettingsController)?.setTitle() (router.backstack.lastOrNull()?.controller() as? SettingsController)?.setTitle()
if (savedInstanceState == null) { if (savedInstanceState == null) {

View File

@ -60,6 +60,7 @@ import eu.kanade.tachiyomi.data.download.model.Download
import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.preference.getOrDefault import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.databinding.MangaDetailsControllerBinding
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
@ -112,7 +113,7 @@ import java.util.Locale
import kotlin.math.max import kotlin.math.max
class MangaDetailsController : class MangaDetailsController :
BaseController, BaseController<MangaDetailsControllerBinding>,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
ActionMode.Callback, ActionMode.Callback,

View File

@ -10,6 +10,7 @@ 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.databinding.MigrationControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController import eu.kanade.tachiyomi.ui.migration.manga.design.PreMigrationController
import eu.kanade.tachiyomi.util.system.await import eu.kanade.tachiyomi.util.system.await
@ -23,7 +24,7 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
class MigrationController : class MigrationController :
NucleusController<MigrationPresenter>(), NucleusController<MigrationControllerBinding, MigrationPresenter>(),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
SourceAdapter.OnAllClickListener, SourceAdapter.OnAllClickListener,
MigrationInterface { MigrationInterface {

View File

@ -15,6 +15,7 @@ import com.google.android.material.bottomsheet.BottomSheetDialog
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.PreMigrationControllerBinding
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
@ -31,7 +32,7 @@ import kotlinx.android.synthetic.main.pre_migration_controller.*
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
class PreMigrationController(bundle: Bundle? = null) : class PreMigrationController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<PreMigrationControllerBinding>(bundle),
FlexibleAdapter FlexibleAdapter
.OnItemClickListener, .OnItemClickListener,
StartMigrationListener { StartMigrationListener {

View File

@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toMangaInfo import eu.kanade.tachiyomi.data.database.models.toMangaInfo
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.databinding.MigrationListControllerBinding
import eu.kanade.tachiyomi.smartsearch.SmartSearchEngine import eu.kanade.tachiyomi.smartsearch.SmartSearchEngine
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
@ -60,7 +61,7 @@ import java.util.concurrent.atomic.AtomicInteger
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
class MigrationListController(bundle: Bundle? = null) : class MigrationListController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<MigrationListControllerBinding>(bundle),
MigrationProcessAdapter.MigrationProcessInterface, MigrationProcessAdapter.MigrationProcessInterface,
BottomNavBarInterface, BottomNavBarInterface,
CoroutineScope { CoroutineScope {

View File

@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download 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.data.notification.Notifications import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.databinding.RecentChaptersControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
@ -38,7 +39,7 @@ import timber.log.Timber
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class RecentChaptersController(bundle: Bundle? = null) : class RecentChaptersController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<RecentChaptersControllerBinding>(bundle),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnUpdateListener, FlexibleAdapter.OnUpdateListener,
FlexibleAdapter.OnItemMoveListener, FlexibleAdapter.OnItemMoveListener,

View File

@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupRestoreService import eu.kanade.tachiyomi.data.backup.BackupRestoreService
import eu.kanade.tachiyomi.data.database.models.History import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.RecentlyReadControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.reader.ReaderActivity
@ -33,7 +34,7 @@ import kotlinx.android.synthetic.main.recently_read_controller.*
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class RecentlyReadController(bundle: Bundle? = null) : class RecentlyReadController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<RecentlyReadControllerBinding>(bundle),
FlexibleAdapter.OnUpdateListener, FlexibleAdapter.OnUpdateListener,
FlexibleAdapter.EndlessScrollListener, FlexibleAdapter.EndlessScrollListener,
RecentlyReadAdapter.OnRemoveClickListener, RecentlyReadAdapter.OnRemoveClickListener,

View File

@ -27,6 +27,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadService import eu.kanade.tachiyomi.data.download.DownloadService
import eu.kanade.tachiyomi.data.download.model.Download 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.databinding.RecentsControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.BaseController import eu.kanade.tachiyomi.ui.base.controller.BaseController
import eu.kanade.tachiyomi.ui.main.BottomSheetController import eu.kanade.tachiyomi.ui.main.BottomSheetController
import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
@ -68,7 +69,7 @@ import kotlin.math.max
* UI related actions should be called from here. * UI related actions should be called from here.
*/ */
class RecentsController(bundle: Bundle? = null) : class RecentsController(bundle: Bundle? = null) :
BaseController(bundle), BaseController<RecentsControllerBinding>(bundle),
RecentMangaAdapter.RecentsInterface, RecentMangaAdapter.RecentsInterface,
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,

View File

@ -101,7 +101,7 @@ abstract class SettingsController : PreferenceController() {
fun setTitle() { fun setTitle() {
var parentController = parentController var parentController = parentController
while (parentController != null) { while (parentController != null) {
if (parentController is BaseController && parentController.getTitle() != null) { if (parentController is BaseController<*> && parentController.getTitle() != null) {
return return
} }
parentController = parentController.parentController parentController = parentController.parentController

View File

@ -10,6 +10,7 @@ import android.view.ViewGroup
import androidx.appcompat.widget.SearchView import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.SettingsSearchControllerBinding
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.ui.setting.SettingsController
import eu.kanade.tachiyomi.util.view.liftAppbarWith import eu.kanade.tachiyomi.util.view.liftAppbarWith
@ -21,7 +22,7 @@ import kotlinx.android.synthetic.main.settings_search_controller.*
* [SettingsSearchAdapter.OnTitleClickListener] called when preference is clicked in settings search * [SettingsSearchAdapter.OnTitleClickListener] called when preference is clicked in settings search
*/ */
class SettingsSearchController : class SettingsSearchController :
NucleusController<SettingsSearchPresenter>(), NucleusController<SettingsSearchControllerBinding, SettingsSearchPresenter>(),
SettingsSearchAdapter.OnTitleClickListener { SettingsSearchAdapter.OnTitleClickListener {
/** /**

View File

@ -24,6 +24,7 @@ import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
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.databinding.SourceControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
@ -75,7 +76,7 @@ import kotlin.math.min
* [SourceAdapter.OnLatestClickListener] call function data on latest item click * [SourceAdapter.OnLatestClickListener] call function data on latest item click
*/ */
class SourceController : class SourceController :
NucleusController<SourcePresenter>(), NucleusController<SourceControllerBinding, SourcePresenter>(),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
SourceAdapter.SourceListener, SourceAdapter.SourceListener,
RootSearchInterface, RootSearchInterface,

View File

@ -21,6 +21,7 @@ import eu.kanade.tachiyomi.data.database.models.Category
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.databinding.BrowseSourceControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
@ -57,7 +58,7 @@ import java.util.concurrent.TimeUnit
* Controller to manage the catalogues available in the app. * Controller to manage the catalogues available in the app.
*/ */
open class BrowseSourceController(bundle: Bundle) : open class BrowseSourceController(bundle: Bundle) :
NucleusController<BrowseSourcePresenter>(bundle), NucleusController<BrowseSourceControllerBinding, BrowseSourcePresenter>(bundle),
FlexibleAdapter.OnItemClickListener, FlexibleAdapter.OnItemClickListener,
FlexibleAdapter.OnItemLongClickListener, FlexibleAdapter.OnItemLongClickListener,
FlexibleAdapter.EndlessScrollListener, FlexibleAdapter.EndlessScrollListener,

View File

@ -11,6 +11,7 @@ import androidx.appcompat.widget.SearchView
import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents import com.jakewharton.rxbinding.support.v7.widget.queryTextChangeEvents
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.databinding.SourceGlobalSearchControllerBinding
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.ui.base.controller.NucleusController
import eu.kanade.tachiyomi.ui.manga.MangaDetailsController import eu.kanade.tachiyomi.ui.manga.MangaDetailsController
@ -28,7 +29,7 @@ import kotlinx.android.synthetic.main.source_global_search_controller.*
open class GlobalSearchController( open class GlobalSearchController(
protected val initialQuery: String? = null, protected val initialQuery: String? = null,
protected val extensionFilter: String? = null protected val extensionFilter: String? = null
) : NucleusController<GlobalSearchPresenter>(), ) : NucleusController<SourceGlobalSearchControllerBinding, GlobalSearchPresenter>(),
GlobalSearchCardAdapter.OnMangaClickListener { GlobalSearchCardAdapter.OnMangaClickListener {
/** /**